CVE-2017-16806: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') (CWE-22)
value: The Process function in RemoteTaskServer/WebServer/HttpServer.cs in Ulterius before 1.9.5.0 allows HTTP server directory traversal.
CWE description: The product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.
CVSS v3 base score: 7.5
Published: 2017-11-13T21:29Z
Repository: https://github.com/Ulterius/server
Language: C#
Files changed: .gitignore, RemoteTaskServer/Api/Network/Messages/MessageBuilder.cs, RemoteTaskServer/Api/Network/Models/SystemInformation.cs, RemoteTaskServer/Api/Network/PacketHandlers/AccountPacketHandler.cs, RemoteTaskServer/Api/Network/PacketHandlers/DisplayPacketHandler.cs, RemoteTaskServer/Api/Network/PacketHandlers/FilePacketHandler.cs, RemoteTaskServer/Api/Network/PacketHandlers/GpuPacketHandler.cs, RemoteTaskServer/Api/Network/PacketHandlers/ProcessPacketHandler.cs, RemoteTaskServer/Api/Network/PacketHandlers/ScreenSharePacketHandler.cs, RemoteTaskServer/Api/Network/PacketHandlers/ServerPacketHandler.cs, RemoteTaskServer/Api/Network/PacketHandlers/SettingsPacketHandler.cs, RemoteTaskServer/Api/Services/LocalSystem/SystemService.cs, RemoteTaskServer/Api/Services/Network/NetworkService.cs, RemoteTaskServer/Api/Services/Update/UpdateService.cs, RemoteTaskServer/Api/SystemData.cs, RemoteTaskServer/Api/UlteriusApiServer.cs, RemoteTaskServer/Api/Win32/Desktop.cs, RemoteTaskServer/Api/Win32/DesktopWatcher.cs, RemoteTaskServer/Api/Win32/Display.cs, RemoteTaskServer/Api/Win32/ScreenShare/DesktopDuplication/DesktopDuplicationException.cs, RemoteTaskServer/Api/Win32/ScreenShare/DesktopDuplication/DesktopDuplicator.cs, RemoteTaskServer/Api/Win32/ScreenShare/DesktopDuplication/DesktopFrame.cs, RemoteTaskServer/Api/Win32/ScreenShare/DesktopDuplication/FinishedRegions.cs, RemoteTaskServer/Api/Win32/ScreenShare/DesktopDuplication/MovedRegion.cs, RemoteTaskServer/Api/Win32/ScreenShare/Models/DisplayInformation.cs, RemoteTaskServer/Api/Win32/ScreenShare/Models/FrameInformation.cs, RemoteTaskServer/Api/Win32/ScreenShare/Models/ResolutionInformation.cs, RemoteTaskServer/Api/Win32/ScreenShare/ScreenData.cs, RemoteTaskServer/Api/Win32/SessionInfo.cs, RemoteTaskServer/Api/Win32/Win32Exception.cs, RemoteTaskServer/Api/Win32/WinApi.cs, RemoteTaskServer/Api/Win32/WindowsIdentityImpersonator.cs, RemoteTaskServer/App.config, RemoteTaskServer/Forms/Utilities/UlteriusTray.cs, RemoteTaskServer/Program.cs, RemoteTaskServer/Properties/AssemblyInfo.cs, RemoteTaskServer/TerminalServer/Messaging/TerminalControl/Handlers/InputTerminalRequestHandler.cs, RemoteTaskServer/TerminalServer/Messaging/WebSocketHandler.cs, RemoteTaskServer/TerminalServer/Messaging/WebSocketQueueServer.cs, RemoteTaskServer/Ulterius.cs, RemoteTaskServer/UlteriusServer.csproj, RemoteTaskServer/UlteriusServer.csproj.DotSettings, RemoteTaskServer/Utilities/AppEnvironment.cs, RemoteTaskServer/Utilities/Config.cs, RemoteTaskServer/Utilities/ExceptionHandler.cs, RemoteTaskServer/Utilities/Extensions/ProcessExtensions.cs, RemoteTaskServer/Utilities/Extensions/StringExtensions.cs, RemoteTaskServer/Utilities/Security/AuthUtils.cs, RemoteTaskServer/Utilities/Tools.cs, RemoteTaskServer/Utilities/Trace.cs, RemoteTaskServer/WebCams/WebCamManager.cs, RemoteTaskServer/WebServer/HttpServer.cs, RemoteTaskServer/WebSocketAPI/WebSocketEventListener.cs, RemoteTaskServer/packages.config, UlteriusAgent/App.config, UlteriusAgent/Program.cs, UlteriusAgent/UlteriusAgent.cs, UlteriusAgent/UlteriusAgent.csproj, UlteriusAgent/packages.config, UlteriusServer.sln
Commit date: 2017-10-23 04:28:07 -0400
Commit message: Stability patch, fixes broken GPU detection code, updates the websocket framework to be real-time, removes crappy agent spawning system, removes IPC, fixes HTTP server traversal,

Diff: diff --git a/.gitignore b/.gitignore
index dd701dc..a736671 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,10 +16,11 @@ TestResults
 
 # Build results
 [Dd]ebug/
 [Rr]elease/
 x64/
+.vs/
 *_i.c
 *_p.c
 *.ilk
 *.meta
 *.obj
diff --git a/AgentInterface/AgentInterface.csproj b/AgentInterface/AgentInterface.csproj
deleted file mode 100644
index 3b092db..0000000
--- a/AgentInterface/AgentInterface.csproj
+++ /dev/null
@@ -1,163 +0,0 @@
-﻿<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
-  <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProjectGuid>{5C3B0B17-CBB7-4B4B-B527-1FAB2BB96466}</ProjectGuid>
-    <OutputType>Library</OutputType>
-    <AppDesignerFolder>Properties</AppDesignerFolder>
-    <RootNamespace>AgentInterface</RootNamespace>
-    <AssemblyName>AgentInterface</AssemblyName>
-    <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
-    <FileAlignment>512</FileAlignment>
-    <NuGetPackageImportStamp>
-    </NuGetPackageImportStamp>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
-  </PropertyGroup>
-  <PropertyGroup>
-    <SignAssembly>true</SignAssembly>
-  </PropertyGroup>
-  <ItemGroup>
-    <Reference Include="Cassia, Version=2.0.0.60, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\Cassia.2.0.0.60\lib\2.0\Cassia.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
-      <HintPath>..\packages\Newtonsoft.Json.10.0.1-beta1\lib\net45\Newtonsoft.Json.dll</HintPath>
-    </Reference>
-    <Reference Include="OpenHardwareMonitorLib, Version=0.7.1.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\OpenHardwareMonitor.0.7.1\lib\net40\OpenHardwareMonitorLib.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="PresentationCore" />
-    <Reference Include="PresentationFramework" />
-    <Reference Include="SharpDX, Version=3.1.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
-      <HintPath>..\packages\SharpDX.3.1.1\lib\net45\SharpDX.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="SharpDX.Direct3D11, Version=3.1.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
-      <HintPath>..\packages\SharpDX.Direct3D11.3.1.1\lib\net45\SharpDX.Direct3D11.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="SharpDX.DXGI, Version=3.1.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
-      <HintPath>..\packages\SharpDX.DXGI.3.1.1\lib\net45\SharpDX.DXGI.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="SharpDX.Mathematics, Version=3.1.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
-      <HintPath>..\packages\SharpDX.Mathematics.3.1.1\lib\net45\SharpDX.Mathematics.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="System" />
-    <Reference Include="System.Core" />
-    <Reference Include="System.Drawing" />
-    <Reference Include="System.Runtime.Serialization" />
-    <Reference Include="System.ServiceModel" />
-    <Reference Include="System.Windows.Forms" />
-    <Reference Include="TurboJpegWrapper, Version=1.4.2.19498, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\TurboJpegWrapper.1.4.2.6\lib\net35\TurboJpegWrapper.dll</HintPath>
-    </Reference>
-    <Reference Include="WindowsBase" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="Api\Models\DisplayInformation.cs" />
-    <Compile Include="Api\Models\FrameInformation.cs" />
-    <Compile Include="Api\Models\ResolutionInformation.cs" />
-    <Compile Include="Api\ScreenShare\DesktopDuplication\DesktopDuplicationException.cs" />
-    <Compile Include="Api\ScreenShare\DesktopDuplication\DesktopDuplicator.cs" />
-    <Compile Include="Api\ScreenShare\DesktopDuplication\DesktopFrame.cs" />
-    <Compile Include="Api\ScreenShare\DesktopDuplication\MovedRegion.cs" />
-    <Compile Include="Api\ScreenShare\DesktopDuplication\FinishedRegions.cs" />
-    <Compile Include="Api\ScreenShare\ScreenData.cs" />
-    <Compile Include="Api\System\SystemData.cs" />
-    <Compile Include="Api\Win32\Desktop.cs" />
-    <Compile Include="Api\Win32\Display.cs" />
-    <Compile Include="Api\Win32\ProcessStarter.cs" />
-    <Compile Include="Api\Win32\SessionInfo.cs" />
-    <Compile Include="Api\Win32\Win32Exception.cs" />
-    <Compile Include="Api\Win32\WinApi.cs" />
-    <Compile Include="Api\Win32\WindowsIdentityImpersonator.cs" />
-    <Compile Include="FrameContract.cs" />
-    <Compile Include="InputContract.cs" />
-    <Compile Include="Properties\AssemblyInfo.cs" />
-    <Compile Include="Settings\AppEnvironment.cs" />
-    <Compile Include="Settings\Config.cs" />
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="packages.config" />
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="FodyWeavers.xml">
-      <SubType>Designer</SubType>
-    </None>
-  </ItemGroup>
-  <ItemGroup />
-  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
-  <UsingTask TaskName="CosturaCleanup" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" TaskFactory="CodeTaskFactory">
-    <ParameterGroup>
-      <Config Output="false" Required="true" ParameterType="Microsoft.Build.Framework.ITaskItem" />
-      <Files Output="false" Required="true" ParameterType="Microsoft.Build.Framework.ITaskItem[]" />
-    </ParameterGroup>
-    <Task Evaluate="true">
-      <Reference xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Include="System.Xml" />
-      <Reference xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Include="System.Xml.Linq" />
-      <Using xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Namespace="System" />
-      <Using xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Namespace="System.IO" />
-      <Using xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Namespace="System.Xml.Linq" />
-      <Code xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Type="Fragment" Language="cs"><![CDATA[
-var config = XElement.Load(Config.ItemSpec).Elements("Costura").FirstOrDefault();
-
-if (config == null) return true;
-
-var excludedAssemblies = new List<string>();
-var attribute = config.Attribute("ExcludeAssemblies");
-if (attribute != null)
-    foreach (var item in attribute.Value.Split('|').Select(x => x.Trim()).Where(x => x != string.Empty))
-        excludedAssemblies.Add(item);
-var element = config.Element("ExcludeAssemblies");
-if (element != null)
-    foreach (var item in element.Value.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()).Where(x => x != string.Empty))
-        excludedAssemblies.Add(item);
-
-var filesToCleanup = Files.Select(f => f.ItemSpec).Where(f => !excludedAssemblies.Contains(Path.GetFileNameWithoutExtension(f), StringComparer.InvariantCultureIgnoreCase));
-
-foreach (var item in filesToCleanup)
-  File.Delete(item);
-]]></Code>
-    </Task>
-  </UsingTask>
-  <Target Name="CleanReferenceCopyLocalPaths" AfterTargets="AfterBuild;NonWinFodyTarget">
-    <CosturaCleanup Config="FodyWeavers.xml" Files="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" />
-  </Target>
-  <Import Project="..\packages\TurboJpegWrapper.1.4.2.6\build\TurboJpegWrapper.targets" Condition="Exists('..\packages\TurboJpegWrapper.1.4.2.6\build\TurboJpegWrapper.targets')" />
-  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
-    <PropertyGroup>
-      <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
-    </PropertyGroup>
-    <Error Condition="!Exists('..\packages\TurboJpegWrapper.1.4.2.6\build\TurboJpegWrapper.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\TurboJpegWrapper.1.4.2.6\build\TurboJpegWrapper.targets'))" />
-  </Target>
-  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
-       Other similar extension points exist, see Microsoft.Common.targets.
-  <Target Name="BeforeBuild">
-  </Target>
-  <Target Name="AfterBuild">
-  </Target>
-  -->
-</Project>
\ No newline at end of file
diff --git a/AgentInterface/Api/Win32/Display.cs b/AgentInterface/Api/Win32/Display.cs
deleted file mode 100644
index c58d49d..0000000
--- a/AgentInterface/Api/Win32/Display.cs
+++ /dev/null
@@ -1,910 +0,0 @@
-﻿#region
-
-using System;
-using System.Collections.Generic;
-using System.Drawing;
-using System.Globalization;
-using System.Linq;
-using System.Runtime.InteropServices;
-using System.Text.RegularExpressions;
-using System.Windows.Forms;
-using AgentInterface.Api.Models;
-using AgentInterface.Api.ScreenShare;
-
-#endregion
-
-namespace AgentInterface.Api.Win32
-{
-    public class Display
-    {
-       
-       
-        [Flags]
-        public enum ChangeDisplaySettingsFlags : uint
-        {
-            CDS_NONE = 0,
-            CDS_UPDATEREGISTRY = 0x00000001,
-            CDS_TEST = 0x00000002,
-            CDS_FULLSCREEN = 0x00000004,
-            CDS_GLOBAL = 0x00000008,
-            CDS_SET_PRIMARY = 0x00000010,
-            CDS_VIDEOPARAMETERS = 0x00000020,
-            CDS_ENABLE_UNSAFE_MODES = 0x00000100,
-            CDS_DISABLE_UNSAFE_MODES = 0x00000200,
-            CDS_RESET = 0x40000000,
-            CDS_RESET_EX = 0x20000000,
-            CDS_NORESET = 0x10000000
-        }
-
-        [Flags]
-        public enum DisplayDeviceStateFlags
-        {
-            /// <summary>The device is part of the desktop.</summary>
-            AttachedToDesktop = 0x1,
-            MultiDriver = 0x2,
-
-            /// <summary>The device is part of the desktop.</summary>
-            PrimaryDevice = 0x4,
-
-            /// <summary>Represents a pseudo device used to mirror application drawing for remoting or other purposes.</summary>
-            MirroringDriver = 0x8,
-
-            /// <summary>The device is VGA compatible.</summary>
-            VgaCompatible = 0x10,
-
-            /// <summary>The device is removable; it cannot be the primary display.</summary>
-            Removable = 0x20,
-
-            /// <summary>The device has more display modes than its output devices support.</summary>
-            ModesPruned = 0x8000000,
-            Remote = 0x4000000,
-            Disconnect = 0x2000000
-        }
-
-        public const int DMDO_DEFAULT = 0;
-        public const int DMDO_90 = 1;
-        public const int DMDO_180 = 2;
-        public const int DMDO_270 = 3;
-
-        public const int ErrorSuccess = 0;
-
-        public const int ENUM_CURRENT_SETTINGS = -1;
-        public const int CDS_UPDATEREGISTRY = 0x01;
-        public const int CDS_TEST = 0x02;
-
-
-        private const int ENUM_REGISTRY_SETTINGS = -2;
-
-        public static int EnumCurrentSettings { get; } = -1;
-
-        public static int EnumRegistrySettings { get; } = -2;
-
-        private static string MonitorFriendlyName(Luid adapterId, uint targetId)
-        {
-            var deviceName = new DisplayconfigTargetDeviceName
-            {
-                header =
-                {
-                    size = (uint) Marshal.SizeOf(typeof(DisplayconfigTargetDeviceName)),
-                    adapterId = adapterId,
-                    id = targetId,
-                    type = DisplayconfigDeviceInfoType.DisplayconfigDeviceInfoGetTargetName
-                }
-            };
-            var error = DisplayConfigGetDeviceInfo(ref deviceName);
-            if (error != ErrorSuccess)
-                throw new Win32Exception(error);
-            return deviceName.monitorFriendlyDeviceName;
-        }
-
-        private static IEnumerable<string> GetAllMonitorsFriendlyNames()
-        {
-            uint pathCount, modeCount;
-            var error = GetDisplayConfigBufferSizes(QueryDeviceConfigFlags.QdcOnlyActivePaths, out pathCount,
-                out modeCount);
-            if (error != ErrorSuccess)
-                throw new Win32Exception(error);
-
-            var displayPaths = new DisplayconfigPathInfo[pathCount];
-            var displayModes = new DisplayconfigModeInfo[modeCount];
-            error = QueryDisplayConfig(QueryDeviceConfigFlags.QdcOnlyActivePaths,
-                ref pathCount, displayPaths, ref modeCount, displayModes, IntPtr.Zero);
-            if (error != ErrorSuccess)
-                throw new Win32Exception(error);
-
-            for (var i = 0; i < modeCount; i++)
-                if (displayModes[i].infoType == DisplayconfigModeInfoType.DisplayconfigModeInfoTypeTarget)
-                    yield return MonitorFriendlyName(displayModes[i].adapterId, displayModes[i].id);
-        }
-
-        public static List<string> DeviceFriendlyName()
-        {
-            return GetAllMonitorsFriendlyNames().ToList();
-        }
-
-        [DllImport("user32.dll")]
-        public static extern int ChangeDisplaySettings(
-            ref Devmode devMode, int flags);
-
-        [DllImport("user32.dll")]
-        public static extern DISP_CHANGE ChangeDisplaySettingsEx(string lpszDeviceName, ref Devmode lpDevMode,
-            IntPtr hwnd, ChangeDisplaySettingsFlags dwflags, IntPtr lParam);
-
-        [DllImport("user32.dll")]
-        public static extern DISP_CHANGE ChangeDisplaySettingsEx(string lpszDeviceName, IntPtr lpDevMode, IntPtr hwnd,
-            ChangeDisplaySettingsFlags dwflags, IntPtr lParam);
-
-        [DllImport("user32.dll")]
-        public static extern bool EnumDisplaySettings(
-            string deviceName, int modeNum, ref Devmode devMode);
-
-        private static List<DisplayInformation> UpdateDisplays()
-        {
-            var monitors = new List<DisplayInformation>();
-            var d = new DisplayDevice();
-            d.cb = Marshal.SizeOf(d);
-            try
-            {
-                for (uint id = 0; EnumDisplayDevices(null, id, ref d, 0); id++)
-                {
-                    if (d.StateFlags.HasFlag(DisplayDeviceStateFlags.AttachedToDesktop))
-                    {
-                        var device = d.DeviceName;
-
-                        var vDevMode = new Devmode();
-                        var i = 0;
-                        var supportedResolutions = new Dictionary<string, List<ResolutionInformation>>();
-                        while (EnumDisplaySettings(device, i, ref vDevMode))
-                        {
-                            var width = vDevMode.dmPelsWidth;
-                            var height = vDevMode.dmPelsHeight;
-                            var bpp = vDevMode.dmBitsPerPel;
-                            var orientation = vDevMode.dmDisplayOrientation.ToString();
-                            var freq = vDevMode.dmDisplayFrequency;
-                            var resolutionKey = $"{width}x{height}";
-                            var resolution = new ResolutionInformation
-                            {
-                                BitsPerPixel = bpp,
-                                Frequency = freq,
-                                Height = height,
-                                Width = width,
-                                Orientation = orientation
-                            };
-                            if (supportedResolutions.ContainsKey(resolutionKey))
-                            {
-                                supportedResolutions[resolutionKey].Add(resolution);
-                            }
-                            else
-                            {
-                                supportedResolutions.Add(resolutionKey, new List<ResolutionInformation>());
-                                supportedResolutions[resolutionKey].Add(resolution);
-                            }
-                            i++;
-                        }
-                        var cDevMode = new Devmode();
-                        EnumDisplaySettings(device, ENUM_CURRENT_SETTINGS, ref cDevMode);
-
-                        var currentResolution = new ResolutionInformation
-                        {
-                            BitsPerPixel = cDevMode.dmBitsPerPel,
-                            Frequency = cDevMode.dmDisplayFrequency,
-                            Height = cDevMode.dmPelsHeight,
-                            Width = cDevMode.dmPelsWidth,
-                            Orientation = cDevMode.dmDisplayOrientation.ToString(),
-                            X = cDevMode.dmPositionX,
-                            Y = cDevMode.dmPositionY
-                        };
-                        var monitor = new DisplayInformation
-                        {
-                            Primary = d.StateFlags.HasFlag(DisplayDeviceStateFlags.PrimaryDevice),
-                            Attached = d.StateFlags.HasFlag(DisplayDeviceStateFlags.AttachedToDesktop),
-                            Removable = d.StateFlags.HasFlag(DisplayDeviceStateFlags.Removable),
-                            VgaCompatible = d.StateFlags.HasFlag(DisplayDeviceStateFlags.VgaCompatible),
-                            MirroringDriver = d.StateFlags.HasFlag(DisplayDeviceStateFlags.MirroringDriver),
-                            MultiDriver = d.StateFlags.HasFlag(DisplayDeviceStateFlags.MultiDriver),
-                            ModesPruned = d.StateFlags.HasFlag(DisplayDeviceStateFlags.ModesPruned),
-                            Remote = d.StateFlags.HasFlag(DisplayDeviceStateFlags.Remote),
-                            Disconnect = d.StateFlags.HasFlag(DisplayDeviceStateFlags.Disconnect),
-                            FriendlyName = $"{GetAllMonitorsFriendlyNames().ElementAt((int)id)} on {d.DeviceString}",
-                            SupportedResolutions = supportedResolutions,
-                            CurrentResolution = currentResolution,
-                            DeviceName = device
-                        };
-                        monitors.Add(monitor);
-                        d.cb = Marshal.SizeOf(d);
-                        EnumDisplayDevices(d.DeviceName, 0, ref d, 0);
-                    }
-                    d.cb = Marshal.SizeOf(d);
-                }
-                return monitors;
-            }
-            catch
-            {
-
-            }
-            string errorMessage = new Win32Exception(Marshal.GetLastWin32Error()).Message;
-            Console.WriteLine(errorMessage);
-            return monitors;
-        }
-
-        public static List<DisplayInformation> DisplayInformation()
-        { 
-            return UpdateDisplays();
-        }
-
-        public static string SetPrimary(string deviceName)
-        {
-            var id = int.Parse(Regex.Match(deviceName, @"\d+").Value) - 1;
-            var originalMode = new Devmode();
-            originalMode.dmSize = (short) Marshal.SizeOf(originalMode);
-            EnumDisplaySettings(deviceName, ENUM_CURRENT_SETTINGS, ref originalMode);
-            var offsetx = originalMode.dmPositionX;
-            var offsety = originalMode.dmPositionY;
-            originalMode.dmPositionX = 0;
-            originalMode.dmPositionY = 0;
-
-            ChangeDisplaySettingsEx(deviceName, ref originalMode, (IntPtr) null,
-                ChangeDisplaySettingsFlags.CDS_SET_PRIMARY | ChangeDisplaySettingsFlags.CDS_UPDATEREGISTRY |
-                ChangeDisplaySettingsFlags.CDS_NORESET, IntPtr.Zero);
-            var device = new DisplayDevice();
-            device.cb = Marshal.SizeOf(device);
-
-            // Update remaining devices
-            for (uint otherid = 0; EnumDisplayDevices(null, otherid, ref device, 0); otherid++)
-            {
-                if (device.StateFlags.HasFlag(DisplayDeviceStateFlags.AttachedToDesktop) && otherid != id)
-                {
-                    device.cb = Marshal.SizeOf(device);
-                    var otherDeviceMode = new Devmode();
-
-                    EnumDisplaySettings(device.DeviceName, -1, ref otherDeviceMode);
-
-                    otherDeviceMode.dmPositionX -= offsetx;
-                    otherDeviceMode.dmPositionY -= offsety;
-
-                    ChangeDisplaySettingsEx(
-                        device.DeviceName,
-                        ref otherDeviceMode,
-                        (IntPtr) null,
-                        ChangeDisplaySettingsFlags.CDS_UPDATEREGISTRY | ChangeDisplaySettingsFlags.CDS_NORESET,
-                        IntPtr.Zero);
-                }
-
-                device.cb = Marshal.SizeOf(device);
-            }
-
-            // Apply settings
-            return
-                GetMessageForCode(ChangeDisplaySettingsEx(null, IntPtr.Zero, (IntPtr) null,
-                    ChangeDisplaySettingsFlags.CDS_NONE, (IntPtr) null));
-        }
-        [DllImport("kernel32.dll")]
-        public static extern uint GetLastError();
-
-        public static string Rotate(int angle, int width, int height, string deviceName)
-        {
-            var originalMode = new Devmode();
-            originalMode.dmSize = (short) Marshal.SizeOf(originalMode);
-            EnumDisplaySettings(deviceName, ENUM_CURRENT_SETTINGS, ref originalMode);
-
-            // swap height and width
-            var temp = originalMode.dmPelsHeight;
-            originalMode.dmPelsHeight = originalMode.dmPelsWidth;
-            originalMode.dmPelsWidth = temp;
-
-            originalMode.dmPelsWidth = width;
-            originalMode.dmPelsHeight = height;
-            switch (angle)
-            {
-                case 0:
-                    originalMode.dmDisplayOrientation = ScreenOrientation.Angle0;
-                    break;
-                case 90:
-                    originalMode.dmDisplayOrientation = ScreenOrientation.Angle90;
-                    break;
-                case 180:
-                    originalMode.dmDisplayOrientation = ScreenOrientation.Angle180;
-                    break;
-                case 270:
-                    originalMode.dmDisplayOrientation = ScreenOrientation.Angle270;
-                    break;
-            }
-            return GetMessageForCode(ChangeDisplaySettingsEx(deviceName, ref originalMode, IntPtr.Zero,
-                ChangeDisplaySettingsFlags.CDS_UPDATEREGISTRY, IntPtr.Zero));
-        }
-
-        public static string ChangeResolution(string deviceName, int width, int height, int bbp, int freq)
-        {
-            var originalMode = new Devmode();
-            originalMode.dmSize = (short) Marshal.SizeOf(originalMode);
-            EnumDisplaySettings(deviceName, ENUM_CURRENT_SETTINGS, ref originalMode);
-            var newMode = originalMode;
-            newMode.dmDeviceName = deviceName;
-            newMode.dmPelsWidth = width;
-            newMode.dmPelsHeight = height;
-            newMode.dmBitsPerPel = bbp;
-            newMode.dmDisplayFrequency = freq;
-            return GetMessageForCode(ChangeDisplaySettingsEx(deviceName, ref newMode, IntPtr.Zero,
-                ChangeDisplaySettingsFlags.CDS_UPDATEREGISTRY, IntPtr.Zero));
-        }
-
-        private static string GetMessageForCode(DISP_CHANGE code)
-        {
-            string message;
-            switch (code)
-            {
-                case DISP_CHANGE.Successful:
-                    message = "Resolution updated.";
-                    break;
-                case DISP_CHANGE.Restart:
-                    message = "A restart is required for this resolution to take effect.";
-                    break;
-                case DISP_CHANGE.BadMode:
-                    message = $"resolution is not valid.";
-                    break;
-                case DISP_CHANGE.BadDualView:
-                    message = "The settings change was unsuccessful because system is DualView capable.";
-                    break;
-                case DISP_CHANGE.BadFlags:
-                    message = "An invalid set of flags was passed in.";
-                    break;
-                case DISP_CHANGE.BadParam:
-                    message =
-                        "An invalid parameter was passed in. This can include an invalid flag or combination of flags.";
-                    break;
-                case DISP_CHANGE.Failed:
-                    message = "Resolution failed to update.";
-                    break;
-                case DISP_CHANGE.NotUpdated:
-                    message = "Unable to write settings to the registry.";
-                    break;
-                default:
-                    message = "Unknown return value from ChangeDisplaySettings API.";
-                    break;
-            }
-            return message;
-        }
-
-        [DllImport("user32.dll")]
-        private static extern bool EnumDisplayDevices(string lpDevice, uint iDevNum, ref DisplayDevice lpDisplayDevice,
-            uint dwFlags);
-
-        public enum DISP_CHANGE
-        {
-            Successful = 0,
-            Restart = 1,
-            Failed = -1,
-            BadMode = -2,
-            NotUpdated = -3,
-            BadFlags = -4,
-            BadParam = -5,
-            BadDualView = -6
-        }
-
-        [StructLayout(LayoutKind.Sequential)]
-        public struct Devmode
-        {
-            private const int Cchdevicename = 0x20;
-            private const int Cchformname = 0x20;
-            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)] public string dmDeviceName;
-            public short dmSpecVersion;
-            public short dmDriverVersion;
-            public short dmSize;
-            public short dmDriverExtra;
-            public int dmFields;
-            public int dmPositionX;
-            public int dmPositionY;
-            public ScreenOrientation dmDisplayOrientation;
-            public int dmDisplayFixedOutput;
-            public short dmColor;
-            public short dmDuplex;
-            public short dmYResolution;
-            public short dmTTOption;
-            public short dmCollate;
-            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)] public string dmFormName;
-            public short dmLogPixels;
-            public int dmBitsPerPel;
-            public int dmPelsWidth;
-            public int dmPelsHeight;
-            public int dmDisplayFlags;
-            public int dmDisplayFrequency;
-            public int dmICMMethod;
-            public int dmICMIntent;
-            public int dmMediaType;
-            public int dmDitherType;
-            public int dmReserved1;
-            public int dmReserved2;
-            public int dmPanningWidth;
-            public int dmPanningHeight;
-        }
-
-        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
-        public struct DisplayDevice
-        {
-            [MarshalAs(UnmanagedType.U4)] public int cb;
-            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string DeviceName;
-            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string DeviceString;
-            [MarshalAs(UnmanagedType.U4)] public DisplayDeviceStateFlags StateFlags;
-            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string DeviceID;
-            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string DeviceKey;
-        }
-
-        #region enums
-
-        public enum QueryDeviceConfigFlags : uint
-        {
-            QdcAllPaths = 0x00000001,
-            QdcOnlyActivePaths = 0x00000002,
-            QdcDatabaseCurrent = 0x00000004
-        }
-
-        public enum DisplayconfigVideoOutputTechnology : uint
-        {
-            DisplayconfigOutputTechnologyOther = 0xFFFFFFFF,
-            DisplayconfigOutputTechnologyHd15 = 0,
-            DisplayconfigOutputTechnologySvideo = 1,
-            DisplayconfigOutputTechnologyCompositeVideo = 2,
-            DisplayconfigOutputTechnologyComponentVideo = 3,
-            DisplayconfigOutputTechnologyDvi = 4,
-            DisplayconfigOutputTechnologyHdmi = 5,
-            DisplayconfigOutputTechnologyLvds = 6,
-            DisplayconfigOutputTechnologyDJpn = 8,
-            DisplayconfigOutputTechnologySdi = 9,
-            DisplayconfigOutputTechnologyDisplayportExternal = 10,
-            DisplayconfigOutputTechnologyDisplayportEmbedded = 11,
-            DisplayconfigOutputTechnologyUdiExternal = 12,
-            DisplayconfigOutputTechnologyUdiEmbedded = 13,
-            DisplayconfigOutputTechnologySdtvdongle = 14,
-            DisplayconfigOutputTechnologyMiracast = 15,
-            DisplayconfigOutputTechnologyInternal = 0x80000000,
-            DisplayconfigOutputTechnologyForceUint32 = 0xFFFFFFFF
-        }
-
-        public enum DisplayconfigScanlineOrdering : uint
-        {
-            DisplayconfigScanlineOrderingUnspecified = 0,
-            DisplayconfigScanlineOrderingProgressive = 1,
-            DisplayconfigScanlineOrderingInterlaced = 2,
-            DisplayconfigScanlineOrderingInterlacedUpperfieldfirst = DisplayconfigScanlineOrderingInterlaced,
-            DisplayconfigScanlineOrderingInterlacedLowerfieldfirst = 3,
-            DisplayconfigScanlineOrderingForceUint32 = 0xFFFFFFFF
-        }
-
-        public enum DisplayconfigRotation : uint
-        {
-            DisplayconfigRotationIdentity = 1,
-            DisplayconfigRotationRotate90 = 2,
-            DisplayconfigRotationRotate180 = 3,
-            DisplayconfigRotationRotate270 = 4,
-            DisplayconfigRotationForceUint32 = 0xFFFFFFFF
-        }
-
-        public enum DisplayconfigScaling : uint
-        {
-            DisplayconfigScalingIdentity = 1,
-            DisplayconfigScalingCentered = 2,
-            DisplayconfigScalingStretched = 3,
-            DisplayconfigScalingAspectratiocenteredmax = 4,
-            DisplayconfigScalingCustom = 5,
-            DisplayconfigScalingPreferred = 128,
-            DisplayconfigScalingForceUint32 = 0xFFFFFFFF
-        }
-        [DllImport("user32")]
-        private static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lpRect, MonitorEnumProc callback, int dwData);
-
-        private delegate bool MonitorEnumProc(IntPtr hDesktop, IntPtr hdc, ref Rect pRect, int dwData);
-
-        [StructLayout(LayoutKind.Sequential)]
-        private struct Rect
-        {
-            public int left;
-            public int top;
-            public int right;
-            public int bottom;
-        }
-
-        public enum DisplayconfigPixelformat : uint
-        {
-            DisplayconfigPixelformat8Bpp = 1,
-            DisplayconfigPixelformat16Bpp = 2,
-            DisplayconfigPixelformat24Bpp = 3,
-            DisplayconfigPixelformat32Bpp = 4,
-            DisplayconfigPixelformatNongdi = 5,
-            DisplayconfigPixelformatForceUint32 = 0xffffffff
-        }
-
-        public enum DisplayconfigModeInfoType : uint
-        {
-            DisplayconfigModeInfoTypeSource = 1,
-            DisplayconfigModeInfoTypeTarget = 2,
-            DisplayconfigModeInfoTypeForceUint32 = 0xFFFFFFFF
-        }
-
-        public enum DisplayconfigDeviceInfoType : uint
-        {
-            DisplayconfigDeviceInfoGetSourceName = 1,
-            DisplayconfigDeviceInfoGetTargetName = 2,
-            DisplayconfigDeviceInfoGetTargetPreferredMode = 3,
-            DisplayconfigDeviceInfoGetAdapterName = 4,
-            DisplayconfigDeviceInfoSetTargetPersistence = 5,
-            DisplayconfigDeviceInfoGetTargetBaseType = 6,
-            DisplayconfigDeviceInfoForceUint32 = 0xFFFFFFFF
-        }
-
-        #endregion
-
-        #region structs
-
-        [StructLayout(LayoutKind.Sequential)]
-        public struct Luid
-        {
-            public uint LowPart;
-            public int HighPart;
-        }
-
-        [StructLayout(LayoutKind.Sequential)]
-        public struct DisplayconfigPathSourceInfo
-        {
-            public Luid adapterId;
-            public uint id;
-            public uint modeInfoIdx;
-            public uint statusFlags;
-        }
-
-        [StructLayout(LayoutKind.Sequential)]
-        public struct DisplayconfigPathTargetInfo
-        {
-            public Luid adapterId;
-            public uint id;
-            public uint modeInfoIdx;
-            private readonly DisplayconfigVideoOutputTechnology outputTechnology;
-            private readonly DisplayconfigRotation rotation;
-            private readonly DisplayconfigScaling scaling;
-            private readonly DisplayconfigRational refreshRate;
-            private readonly DisplayconfigScanlineOrdering scanLineOrdering;
-            public bool targetAvailable;
-            public uint statusFlags;
-        }
-
-        [StructLayout(LayoutKind.Sequential)]
-        public struct DisplayconfigRational
-        {
-            public uint Numerator;
-            public uint Denominator;
-        }
-
-        [StructLayout(LayoutKind.Sequential)]
-        public struct DisplayconfigPathInfo
-        {
-            public DisplayconfigPathSourceInfo sourceInfo;
-            public DisplayconfigPathTargetInfo targetInfo;
-            public uint flags;
-        }
-
-        [StructLayout(LayoutKind.Sequential)]
-        public struct Displayconfig2Dregion
-        {
-            public uint cx;
-            public uint cy;
-        }
-
-        [StructLayout(LayoutKind.Sequential)]
-        public struct DisplayconfigVideoSignalInfo
-        {
-            public ulong pixelRate;
-            public DisplayconfigRational hSyncFreq;
-            public DisplayconfigRational vSyncFreq;
-            public Displayconfig2Dregion activeSize;
-            public Displayconfig2Dregion totalSize;
-            public uint videoStandard;
-            public DisplayconfigScanlineOrdering scanLineOrdering;
-        }
-
-        [StructLayout(LayoutKind.Sequential)]
-        public struct DisplayconfigTargetMode
-        {
-            public DisplayconfigVideoSignalInfo targetVideoSignalInfo;
-        }
-
-        [StructLayout(LayoutKind.Sequential)]
-        public struct Pointl
-        {
-            private readonly int x;
-            private readonly int y;
-        }
-
-        [StructLayout(LayoutKind.Sequential)]
-        public struct DisplayconfigSourceMode
-        {
-            public uint width;
-            public uint height;
-            public DisplayconfigPixelformat pixelFormat;
-            public Pointl position;
-        }
-
-        [StructLayout(LayoutKind.Explicit)]
-        public struct DisplayconfigModeInfoUnion
-        {
-            [FieldOffset(0)] public DisplayconfigTargetMode targetMode;
-
-            [FieldOffset(0)] public DisplayconfigSourceMode sourceMode;
-        }
-
-        [StructLayout(LayoutKind.Sequential)]
-        public struct DisplayconfigModeInfo
-        {
-            public DisplayconfigModeInfoType infoType;
-            public uint id;
-            public Luid adapterId;
-            public DisplayconfigModeInfoUnion modeInfo;
-        }
-
-        [StructLayout(LayoutKind.Sequential)]
-        public struct DisplayconfigTargetDeviceNameFlags
-        {
-            public uint value;
-        }
-
-        [StructLayout(LayoutKind.Sequential)]
-        public struct DisplayconfigDeviceInfoHeader
-        {
-            public DisplayconfigDeviceInfoType type;
-            public uint size;
-            public Luid adapterId;
-            public uint id;
-        }
-
-        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
-        public struct DisplayconfigTargetDeviceName
-        {
-            public DisplayconfigDeviceInfoHeader header;
-            public DisplayconfigTargetDeviceNameFlags flags;
-            public DisplayconfigVideoOutputTechnology outputTechnology;
-            public ushort edidManufactureId;
-            public ushort edidProductCodeId;
-            public uint connectorInstance;
-
-            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string monitorFriendlyDeviceName;
-
-            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string monitorDevicePath;
-        }
-        [StructLayout(LayoutKind.Sequential)]
-        public struct RECT
-        {
-            public int Left, Top, Right, Bottom;
-
-            public RECT(int left, int top, int right, int bottom)
-            {
-                Left = left;
-                Top = top;
-                Right = right;
-                Bottom = bottom;
-            }
-
-            public RECT(Rectangle r) : this(r.Left, r.Top, r.Right, r.Bottom) { }
-
-            public int X
-            {
-                get { return Left; }
-                set { Right -= (Left - value); Left = value; }
-            }
-
-            public int Y
-            {
-                get { return Top; }
-                set { Bottom -= (Top - value); Top = value; }
-            }
-
-            public int Height
-            {
-                get { return Bottom - Top; }
-                set { Bottom = value + Top; }
-            }
-
-            public int Width
-            {
-                get { return Right - Left; }
-                set { Right = value + Left; }
-            }
-
-            
-
-            public Size Size
-            {
-                get { return new Size(Width, Height); }
-                set { Width = value.Width; Height = value.Height; }
-            }
-
-            public static implicit operator Rectangle(RECT r)
-            {
-                return new Rectangle(r.Left, r.Top, r.Width, r.Height);
-            }
-
-            public static implicit operator RECT(Rectangle r)
-            {
-                return new RECT(r);
-            }
-
-            public static bool operator ==(RECT r1, RECT r2)
-            {
-                return r1.Equals(r2);
-            }
-
-            public static bool operator !=(RECT r1, RECT r2)
-            {
-                return !r1.Equals(r2);
-            }
-
-            public bool Equals(RECT r)
-            {
-                return r.Left == Left && r.Top == Top && r.Right == Right && r.Bottom == Bottom;
-            }
-
-            public override bool Equals(object obj)
-            {
-                if (obj is RECT)
-                    return Equals((RECT)obj);
-                else if (obj is Rectangle)
-                    return Equals(new RECT((Rectangle)obj));
-                return false;
-            }
-
-            public override int GetHashCode()
-            {
-                return ((Rectangle)this).GetHashCode();
-            }
-
-            public override string ToString()
-            {
-                return string.Format(CultureInfo.CurrentCulture, "{{Left={0},Top={1},Right={2},Bottom={3}}}", Left, Top, Right, Bottom);
-            }
-        }
-
-        [StructLayout(LayoutKind.Sequential)]
-        public struct CURSORINFO
-        {
-            public Int32 cbSize;        // Specifies the size, in bytes, of the structure. 
-            public Int32 flags;         // Specifies the cursor state. This parameter can be one of the following values:
-            public IntPtr hCursor;          // Handle to the cursor. 
-            public POINT ptScreenPos;       // A POINT structure that receives the screen coordinates of the cursor. 
-        }
-
-        [StructLayout(LayoutKind.Sequential)]
-        public struct ICONINFO
-        {
-            public bool fIcon;         // Specifies whether this structure defines an icon or a cursor. A value of TRUE specifies 
-            public Int32 xHotspot;     // Specifies the x-coordinate of a cursor's hot spot. If this structure defines an icon, the hot 
-            public Int32 yHotspot;     // Specifies the y-coordinate of the cursor's hot spot. If this structure defines an icon, the hot 
-            public IntPtr hbmMask;     // (HBITMAP) Specifies the icon bitmask bitmap. If this structure defines a black and white icon, 
-            public IntPtr hbmColor;    // (HBITMAP) Handle to the icon color bitmap. This member can be optional if this 
-        }
-
-        [StructLayout(LayoutKind.Sequential)]
-        public struct POINT
-        {
-            public Int32 x;
-            public Int32 y;
-        }
-        public const int Width = 0;
-        public const int Height = 1;
-        public struct ScreenSize
-        {
-            public int Width;
-            public int Height;
-        }
-        public const Int32 CURSOR_SHOWING = 0x00000001;
-
-        [DllImport("user32.dll", EntryPoint = "GetDesktopWindow")]
-        public static extern IntPtr GetDesktopWindow();
-
-        [DllImport("user32.dll", EntryPoint = "GetDC")]
-        public static extern IntPtr GetDesktopContext(IntPtr ptr);
-
-        [DllImport("user32.dll", EntryPoint = "GetSystemMetrics")]
-        public static extern int GetSystemMetrics(int abc);
-
-        [DllImport("user32.dll", EntryPoint = "GetWindowDC")]
-        public static extern IntPtr GetWindowDesktopContext(Int32 ptr);
-
-        [DllImport("user32.dll", EntryPoint = "ReleaseDC")]
-        public static extern IntPtr ReleaseDesktopContext(IntPtr hWnd, IntPtr hDc);
-
-        [DllImport("user32.dll", EntryPoint = "GetCursorInfo")]
-        public static extern bool GetCursorInfo(out CursorInfo pci);
-
-        [DllImport("user32.dll", EntryPoint = "CopyIcon")]
-        public static extern IntPtr CopyIcon(IntPtr hIcon);
-
-        [DllImport("user32.dll", EntryPoint = "GetIconInfo")]
-        public static extern bool GetIconInfo(IntPtr hIcon, out IconInfo piconinfo);
-
-        [DllImport("user32.dll", EntryPoint = "DestroyIcon")]
-        public static extern bool DestroyIcon(IntPtr hIcon);
-        #endregion
-        [StructLayout(LayoutKind.Sequential)]
-        public struct IconInfo
-        {
-            public bool IsIcon;         // Specifies whether this structure defines an icon or a cursor. A value of TRUE specifies 
-            public Int32 Xcoord;     // Specifies the x-coordinate of a cursor's hot spot. If this structure defines an icon, the hot 
-            public Int32 Ycoord;     // Specifies the y-coordinate of the cursor's hot spot. If this structure defines an icon, the hot 
-            public IntPtr Bitmask;     // (HBITMAP) Specifies the icon bitmask bitmap. If this structure defines a black and white icon, 
-            public IntPtr Color;    // (HBITMAP) Handle to the icon color bitmap. This member can be optional if this 
-        }
-
-        [StructLayout(LayoutKind.Sequential)]
-        public struct Point
-        {
-            public Int32 X;
-            public Int32 Y;
-        }
-
-        [StructLayout(LayoutKind.Sequential)]
-        public struct CursorInfo
-        {
-            public Int32 Size;        // Specifies the size, in bytes, of the structure. 
-            public Int32 State;         // Specifies the cursor state. This parameter can be one of the following values:
-            public IntPtr Handle;          // Handle to the cursor. 
-            public Point Coordinates;       // A POINT structure that receives the screen coordinates of the cursor. 
-        }
-
-        #region DLL-Imports
-
-        [DllImport("user32.dll")]
-        public static extern int GetDisplayConfigBufferSizes(
-            QueryDeviceConfigFlags flags, out uint numPathArrayElements, out uint numModeInfoArrayElements);
-
-        [DllImport("user32.dll")]
-        public static extern int QueryDisplayConfig(
-            QueryDeviceConfigFlags flags,
-            ref uint numPathArrayElements, [Out] DisplayconfigPathInfo[] pathInfoArray,
-            ref uint numModeInfoArrayElements, [Out] DisplayconfigModeInfo[] modeInfoArray,
-            IntPtr currentTopologyId
-            );
-
-        [DllImport("user32.dll")]
-        public static extern int DisplayConfigGetDeviceInfo(ref DisplayconfigTargetDeviceName deviceName);
-
-      
-        [DllImport("user32.dll", SetLastError = true)]
-        [return: MarshalAs(UnmanagedType.Bool)]
-       public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
-
-       public static Rectangle GetWindowRectangle()
-        {
-            RECT scBounds = new RECT();
-            GetWindowRect(GetDesktopWindow(), ref scBounds);
-            return scBounds;
-        }
-
-        public const int SRCCOPY = 13369376;
-
-        [DllImport("gdi32.dll", EntryPoint = "CreateDC")]
-        public static extern IntPtr CreateDesktopContext(IntPtr lpszDriver, string lpszDevice, IntPtr lpszOutput, IntPtr lpInitData);
-
-        [DllImport("gdi32.dll", EntryPoint = "DeleteDC")]
-        public static extern IntPtr DeleteDesktopContext(IntPtr hDc);
-
-        [DllImport("gdi32.dll", EntryPoint = "DeleteObject")]
-        public static extern IntPtr DeleteObject(IntPtr hDc);
-
-        [DllImport("gdi32.dll", EntryPoint = "BitBlt")]
-        public static extern bool BitBlt(IntPtr hdcDest, int xDest,
-                                         int yDest, int wDest,
-                                         int hDest, IntPtr hdcSource,
-                                         int xSrc, int ySrc, int rasterOp);
-
-        [DllImport("gdi32.dll", EntryPoint = "CreateCompatibleBitmap")]
-        public static extern IntPtr CreateCompatibleBitmap
-                                    (IntPtr hdc, int nWidth, int nHeight);
-
-        [DllImport("gdi32.dll", EntryPoint = "CreateCompatibleDC")]
-        public static extern IntPtr CreateCompatibleDesktopContext(IntPtr hdc);
-
-        [DllImport("gdi32.dll", EntryPoint = "SelectObject")]
-        public static extern IntPtr SelectObject(IntPtr hdc, IntPtr bmp);
-
-        #endregion
-    }
-
-    
-}
\ No newline at end of file
diff --git a/AgentInterface/Api/Win32/ProcessStarter.cs b/AgentInterface/Api/Win32/ProcessStarter.cs
deleted file mode 100644
index f264db5..0000000
--- a/AgentInterface/Api/Win32/ProcessStarter.cs
+++ /dev/null
@@ -1,247 +0,0 @@
-﻿#region
-
-using System;
-using System.Diagnostics;
-using System.Runtime.InteropServices;
-using System.Security;
-using System.Security.Principal;
-using Cassia;
-
-#endregion
-
-namespace AgentInterface.Api.Win32
-{
-    /// <summary>
-    ///     Class that allows running applications with full admin rights. In
-    ///     addition the application launched will bypass the Vista UAC prompt.
-    /// </summary>
-    public class ProcessStarter
-    {
-
-
-
-        private static int GetUserSessionId(string username)
-        {
-            try
-            {
-                ITerminalServicesManager manager = new TerminalServicesManager();
-                using (ITerminalServer server = manager.GetLocalServer())
-                {
-                    server.Open();
-                    foreach (ITerminalServicesSession session in server.GetSessions())
-                    {
-
-                        NTAccount account = session.UserAccount;
-                        if (account == null) continue;
-                        var userName = account.Value.Split('\\')[1];
-                        if (userName.ToLower().Equals(username.ToLower())) return session.SessionId;
-                    }
-                }
-                return -1;
-            }
-            catch (Exception)
-            {
-
-                return -1;
-            }
-        }
-
-
-        /// <summary>
-        ///     Launches the given application with full admin rights, and in addition bypasses the Vista UAC prompt
-        /// </summary>
-        /// <param name="applicationName">The name of the application to launch</param>
-        /// <param name="procInfo">Process information regarding the launched application that gets returned to the caller</param>
-        /// <returns></returns>
-        public static bool  StartProcessAndBypassUAC(string applicationName, out PROCESS_INFORMATION procInfo)
-        {
-            uint winlogonPid = 0;
-            IntPtr hUserTokenDup = IntPtr.Zero, hPToken = IntPtr.Zero, hProcess = IntPtr.Zero;
-            procInfo = new PROCESS_INFORMATION();
-
-
-            // obtain the currently active session id; every logged on user in the system has a unique session id
-            var dwSessionId = -1;
-
-                dwSessionId = (int) WTSGetActiveConsoleSessionId();
-            
-            // obtain the process id of the winlogon process that is running within the currently active session
-            var processes = Process.GetProcessesByName("winlogon");
-            foreach (var p in processes)
-            {
-                if ((uint) p.SessionId == dwSessionId)
-                {
-                    winlogonPid = (uint) p.Id;
-                }
-            }
-
-            // obtain a handle to the winlogon process
-            hProcess = OpenProcess(MAXIMUM_ALLOWED, false, winlogonPid);
-
-            // obtain a handle to the access token of the winlogon process
-            if (!OpenProcessToken(hProcess, TOKEN_DUPLICATE, ref hPToken))
-            {
-                CloseHandle(hProcess);
-                return false;
-            }
-
-            // Security attibute structure used in DuplicateTokenEx and CreateProcessAsUser
-            // I would prefer to not have to use a security attribute variable and to just 
-            // simply pass null and inherit (by default) the security attributes
-            // of the existing token. However, in C# structures are value types and therefore
-            // cannot be assigned the null value.
-            var sa = new SECURITY_ATTRIBUTES();
-            sa.Length = Marshal.SizeOf(sa);
-
-            // copy the access token of the winlogon process; the newly created token will be a primary token
-            if (
-                !DuplicateTokenEx(hPToken, MAXIMUM_ALLOWED, ref sa,
-                    (int) SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, (int) TOKEN_TYPE.TokenPrimary,
-                    ref hUserTokenDup))
-            {
-                CloseHandle(hProcess);
-                CloseHandle(hPToken);
-                return false;
-            }
-
-            // By default CreateProcessAsUser creates a process on a non-interactive window station, meaning
-            // the window station has a desktop that is invisible and the process is incapable of receiving
-            // user input. To remedy this we set the lpDesktop parameter to indicate we want to enable user 
-            // interaction with the new process.
-            var si = new STARTUPINFO();
-            si.cb = Marshal.SizeOf(si);
-            si.lpDesktop = @"winsta0\default";
-                // interactive window station parameter; basically this indicates that the process created can display a GUI on the desktop
-
-            // flags that specify the priority and creation method of the process
-            var dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
-
-            // create a new process in the current user's logon session
-            var result = CreateProcessAsUser(hUserTokenDup, // client's access token
-                null, // file to execute
-                applicationName, // command line
-                ref sa, // pointer to process SECURITY_ATTRIBUTES
-                ref sa, // pointer to thread SECURITY_ATTRIBUTES
-                false, // handles are not inheritable
-                dwCreationFlags, // creation flags
-                IntPtr.Zero, // pointer to new environment block 
-                null, // name of current directory 
-                ref si, // pointer to STARTUPINFO structure
-                out procInfo // receives information about new process
-                );
-
-            // invalidate the handles
-            CloseHandle(hProcess);
-            CloseHandle(hPToken);
-            CloseHandle(hUserTokenDup);
-
-            return result; // return the result
-        }
-
-        #region Structures
-
-        [StructLayout(LayoutKind.Sequential)]
-        public struct SECURITY_ATTRIBUTES
-        {
-            public int Length;
-            public IntPtr lpSecurityDescriptor;
-            public bool bInheritHandle;
-        }
-
-        [StructLayout(LayoutKind.Sequential)]
-        public struct STARTUPINFO
-        {
-            public int cb;
-            public string lpReserved;
-            public string lpDesktop;
-            public string lpTitle;
-            public uint dwX;
-            public uint dwY;
-            public uint dwXSize;
-            public uint dwYSize;
-            public uint dwXCountChars;
-            public uint dwYCountChars;
-            public uint dwFillAttribute;
-            public uint dwFlags;
-            public short wShowWindow;
-            public short cbReserved2;
-            public IntPtr lpReserved2;
-            public IntPtr hStdInput;
-            public IntPtr hStdOutput;
-            public IntPtr hStdError;
-        }
-
-        [StructLayout(LayoutKind.Sequential)]
-        public struct PROCESS_INFORMATION
-        {
-            public IntPtr hProcess;
-            public IntPtr hThread;
-            public uint dwProcessId;
-            public uint dwThreadId;
-        }
-
-        #endregion
-
-        #region Enumerations
-
-        private enum TOKEN_TYPE
-        {
-            TokenPrimary = 1,
-            TokenImpersonation = 2
-        }
-
-        private enum SECURITY_IMPERSONATION_LEVEL
-        {
-            SecurityAnonymous = 0,
-            SecurityIdentification = 1,
-            SecurityImpersonation = 2,
-            SecurityDelegation = 3
-        }
-
-        #endregion
-
-        #region Constants
-
-        public const int TOKEN_DUPLICATE = 0x0002;
-        public const uint MAXIMUM_ALLOWED = 0x2000000;
-        public const int CREATE_NEW_CONSOLE = 0x00000010;
-
-        public const int IDLE_PRIORITY_CLASS = 0x40;
-        public const int NORMAL_PRIORITY_CLASS = 0x20;
-        public const int HIGH_PRIORITY_CLASS = 0x80;
-        public const int REALTIME_PRIORITY_CLASS = 0x100;
-
-        #endregion
-
-        #region Win32 API Imports
-
-        [DllImport("kernel32.dll", SetLastError = true)]
-        private static extern bool CloseHandle(IntPtr hSnapshot);
-
-        [DllImport("kernel32.dll")]
-        private static extern uint WTSGetActiveConsoleSessionId();
-
-        [DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUser", SetLastError = true, CharSet = CharSet.Ansi,
-            CallingConvention = CallingConvention.StdCall)]
-        public static extern bool CreateProcessAsUser(IntPtr hToken, string lpApplicationName, string lpCommandLine,
-            ref SECURITY_ATTRIBUTES lpProcessAttributes,
-            ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandle, int dwCreationFlags, IntPtr lpEnvironment,
-            string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
-
-        [DllImport("kernel32.dll")]
-        private static extern bool ProcessIdToSessionId(uint dwProcessId, ref uint pSessionId);
-
-        [DllImport("advapi32.dll", EntryPoint = "DuplicateTokenEx")]
-        public static extern bool DuplicateTokenEx(IntPtr ExistingTokenHandle, uint dwDesiredAccess,
-            ref SECURITY_ATTRIBUTES lpThreadAttributes, int TokenType,
-            int ImpersonationLevel, ref IntPtr DuplicateTokenHandle);
-
-        [DllImport("kernel32.dll")]
-        private static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId);
-
-        [DllImport("advapi32", SetLastError = true), SuppressUnmanagedCodeSecurity]
-        private static extern bool OpenProcessToken(IntPtr ProcessHandle, int DesiredAccess, ref IntPtr TokenHandle);
-
-        #endregion
-    }
-}
\ No newline at end of file
diff --git a/AgentInterface/FodyWeavers.xml b/AgentInterface/FodyWeavers.xml
deleted file mode 100644
index 52e39c5..0000000
--- a/AgentInterface/FodyWeavers.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-﻿<?xml version="1.0" encoding="utf-8"?>
-<Weavers>
-  
-</Weavers>
\ No newline at end of file
diff --git a/AgentInterface/FrameContract.cs b/AgentInterface/FrameContract.cs
deleted file mode 100644
index ac79e4d..0000000
--- a/AgentInterface/FrameContract.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-﻿using System.ServiceModel;
-using AgentInterface.Api.Models;
-
-namespace AgentInterface
-{
-    [ServiceContract(Namespace = "https://ulterius.io/")]
-    public interface IFrameContract
-    {
-
-        [OperationContract]
-        FrameInformation GetCleanFrame();
-
-        [OperationContract]
-        FrameInformation GetFullFrame();
-
-        [OperationContract]
-        bool KeepAlive();
-
-    }
-}
\ No newline at end of file
diff --git a/AgentInterface/InputContract.cs b/AgentInterface/InputContract.cs
deleted file mode 100644
index 69e0401..0000000
--- a/AgentInterface/InputContract.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-﻿using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.ServiceModel;
-using System.Text;
-using System.Threading.Tasks;
-using AgentInterface.Api.Models;
-
-namespace AgentInterface
-{
-    [ServiceContract(Namespace = "https://ulterius.io/")]
-    public interface IInputContract
-    {
-
-        [OperationContract(IsOneWay = true)]
-        void HandleRightMouseDown();
-
-        [OperationContract(IsOneWay = true)]
-        void HandleRightMouseUp();
-
-        [OperationContract(IsOneWay = true)]
-        void MoveMouse(int x, int y);
-
-        [OperationContract(IsOneWay = true)]
-        void MouseScroll(bool positive);
-
-        [OperationContract(IsOneWay = true)]
-        void HandleLeftMouseDown();
-
-        [OperationContract(IsOneWay = true)]
-        void HandleLeftMouseUp();
-
-        [OperationContract(IsOneWay = true)]
-        void HandleKeyDown(List<int> keyCodes);
-
-        [OperationContract(IsOneWay = true)]
-        void HandleKeyUp(List<int> keyCodes);
-
-        [OperationContract(IsOneWay = true)]
-        void HandleRightClick();
-
-        [OperationContract]
-        float GetGpuTemp(string gpuName);
-
-        [OperationContract]
-        List<DisplayInformation> GetDisplayInformation();
-
-        [OperationContract]
-        List<float> GetCpuTemps();
-
-    }
-}
diff --git a/AgentInterface/Properties/AssemblyInfo.cs b/AgentInterface/Properties/AssemblyInfo.cs
deleted file mode 100644
index 327ea23..0000000
--- a/AgentInterface/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-﻿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("AgentInterface")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("Octopodal Solutions")]
-[assembly: AssemblyProduct("Ulterius")]
-[assembly: AssemblyCopyright("Copyright ©  2016")]
-[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("5c3b0b17-cbb7-4b4b-b527-1fab2bb96466")]
-
-// 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/AgentInterface/packages.config b/AgentInterface/packages.config
deleted file mode 100644
index 4fbf902..0000000
--- a/AgentInterface/packages.config
+++ /dev/null
@@ -1,11 +0,0 @@
-﻿<?xml version="1.0" encoding="utf-8"?>
-<packages>
-  <package id="Cassia" version="2.0.0.60" targetFramework="net452" />
-  <package id="Newtonsoft.Json" version="10.0.1-beta1" targetFramework="net452" />
-  <package id="OpenHardwareMonitor" version="0.7.1" targetFramework="net452" />
-  <package id="SharpDX" version="3.1.1" targetFramework="net452" />
-  <package id="SharpDX.Direct3D11" version="3.1.1" targetFramework="net452" />
-  <package id="SharpDX.DXGI" version="3.1.1" targetFramework="net452" />
-  <package id="SharpDX.Mathematics" version="3.1.1" targetFramework="net452" />
-  <package id="TurboJpegWrapper" version="1.4.2.6" targetFramework="net452" />
-</packages>
\ No newline at end of file
diff --git a/Deps/OpenHardwareMonitorLib.dll b/Deps/OpenHardwareMonitorLib.dll
new file mode 100644
index 0000000..e059e78
Binary files /dev/null and b/Deps/OpenHardwareMonitorLib.dll differ
diff --git a/RemoteTaskServer/Api/Network/Messages/MessageBuilder.cs b/RemoteTaskServer/Api/Network/Messages/MessageBuilder.cs
index e3a8cfe..0aaea75 100644
--- a/RemoteTaskServer/Api/Network/Messages/MessageBuilder.cs
+++ b/RemoteTaskServer/Api/Network/Messages/MessageBuilder.cs
@@ -5,10 +5,11 @@ using System.IO;
 using System.Text;
 using Newtonsoft.Json;
 using UlteriusServer.Utilities.Security;
 using UlteriusServer.WebSocketAPI.Authentication;
 using vtortola.WebSockets;
+using vtortola.WebSockets.Http;
 using static UlteriusServer.Utilities.Security.UlteriusAes;
 
 #endregion
 
 namespace UlteriusServer.Api.Network.Messages
@@ -39,10 +40,11 @@ namespace UlteriusServer.Api.Network.Messages
         public void WriteMessage(object data)
         {
  
             if (_client != null && data != null)
             {
+                var host = new Uri($"ws://{_client.HttpRequest.Headers[RequestHeader.Host]}", UriKind.Absolute);
                 JsonSerializerSettings settings = new JsonSerializerSettings {ContractResolver = new MessageResolver()};
 
                 var json = JsonConvert.SerializeObject(new
                 {
                     endpoint = Endpoint,
@@ -53,12 +55,15 @@ namespace UlteriusServer.Api.Network.Messages
 
                 try
                 {
                     if (_authClient != null)
                     {
+
                         if (_authClient.AesShook)
                         {
+                           
+
                             var keyBytes = Encoding.UTF8.GetBytes(Rsa.SecureStringToString(_authClient.AesKey));
                             var keyIv = Encoding.UTF8.GetBytes(Rsa.SecureStringToString(_authClient.AesIv));
 
                             var encryptedData = Encrypt(Encoding.UTF8.GetBytes(json), keyBytes, keyIv);
                             using (var memoryStream = new MemoryStream())
@@ -69,11 +74,11 @@ namespace UlteriusServer.Api.Network.Messages
                                     binaryWriter.Write(Encoding.UTF8.GetBytes(Endpoint));
                                     binaryWriter.Write(Encoding.UTF8.GetBytes(EncryptionType.CBC.ToString()));
                                     binaryWriter.Write(encryptedData);
                                 }
                                 var message = new Message(_client, memoryStream.ToArray(), Message.MessageType.Binary);
-                                var targetPort = _client.LocalEndpoint.Port;
+                                var targetPort = host.Port;
                                 _authClient?.MessageQueueManagers[targetPort]?.SendQueue.Add(message);
                             }
                             return;
                         }
                     }
@@ -86,11 +91,11 @@ namespace UlteriusServer.Api.Network.Messages
                     return;
                 }
                 var jsonMessage = new Message(_client, json, Message.MessageType.Text);
                 if (_authClient != null)
                 {
-                    var targetPort = _client.LocalEndpoint.Port;
+                    var targetPort = host.Port;
                     _authClient?.MessageQueueManagers[targetPort]?.SendQueue.Add(jsonMessage);
                 }
             }
         }
 
@@ -102,10 +107,11 @@ namespace UlteriusServer.Api.Network.Messages
         public void WriteScreenFrame(byte[] data)
         {
             if (_client == null || data == null) return;
             try
             {
+                var host = new Uri($"ws://{_client.HttpRequest.Headers[RequestHeader.Host]}", UriKind.Absolute);
                 if (_authClient == null) return;
                 if (!_authClient.AesShook) return;
                 var keyBytes = Encoding.UTF8.GetBytes(Rsa.SecureStringToString(_authClient.AesKey));
                 var keyIv = Encoding.UTF8.GetBytes(Rsa.SecureStringToString(_authClient.AesIv));
 
@@ -119,11 +125,11 @@ namespace UlteriusServer.Api.Network.Messages
                         binaryWriter.Write(Encoding.UTF8.GetBytes(Endpoint));
                         binaryWriter.Write(Encoding.UTF8.GetBytes(EncryptionType.OFB.ToString()));
                         binaryWriter.Write(encryptedData);
                     }
                     var message = new Message(_client, memoryStream.ToArray(), Message.MessageType.Binary);
-                    var targetPort = _client.LocalEndpoint.Port;
+                    var targetPort = host.Port;
                     _authClient?.MessageQueueManagers[targetPort]?.SendQueue.Add(message);
                 }
             }
             catch (Exception e)
             {
diff --git a/RemoteTaskServer/Api/Network/Models/SystemInformation.cs b/RemoteTaskServer/Api/Network/Models/SystemInformation.cs
index a2b00a1..441966e 100644
--- a/RemoteTaskServer/Api/Network/Models/SystemInformation.cs
+++ b/RemoteTaskServer/Api/Network/Models/SystemInformation.cs
@@ -1,9 +1,9 @@
 ﻿#region
 
 using System.Collections.Generic;
-using AgentInterface.Api.Models;
+using UlteriusServer.Api.Win32.ScreenShare.Models;
 
 #endregion
 
 namespace UlteriusServer.Api.Network.Models
 
diff --git a/RemoteTaskServer/Api/Network/PacketHandlers/AccountPacketHandler.cs b/RemoteTaskServer/Api/Network/PacketHandlers/AccountPacketHandler.cs
index f974117..f7e03f2 100644
--- a/RemoteTaskServer/Api/Network/PacketHandlers/AccountPacketHandler.cs
+++ b/RemoteTaskServer/Api/Network/PacketHandlers/AccountPacketHandler.cs
@@ -4,11 +4,10 @@ using System;
 using System.Drawing;
 using System.Drawing.Imaging;
 using System.IO;
 using System.Runtime.InteropServices;
 using System.Text;
-using AgentInterface.Settings;
 using UlteriusServer.Api.Network.Messages;
 using UlteriusServer.Utilities;
 using UlteriusServer.WebSocketAPI.Authentication;
 using vtortola.WebSockets;
 
diff --git a/RemoteTaskServer/Api/Network/PacketHandlers/DisplayPacketHandler.cs b/RemoteTaskServer/Api/Network/PacketHandlers/DisplayPacketHandler.cs
index bd97a87..1cea03c 100644
--- a/RemoteTaskServer/Api/Network/PacketHandlers/DisplayPacketHandler.cs
+++ b/RemoteTaskServer/Api/Network/PacketHandlers/DisplayPacketHandler.cs
@@ -1,9 +1,9 @@
 ﻿#region
 
-using AgentInterface.Api.Win32;
 using UlteriusServer.Api.Network.Messages;
+using UlteriusServer.Api.Win32;
 using UlteriusServer.WebSocketAPI.Authentication;
 using vtortola.WebSockets;
 
 #endregion
 
@@ -41,45 +41,45 @@ namespace UlteriusServer.Api.Network.PacketHandlers
             }
         }
 
         private void SetPrimaryDisplay()
         {
-            var device = _packet.Args[0].ToString();
+           /* var device = _packet.Args[0].ToString();
             var message =  Display.SetPrimary(device);
             var formThread = new
             {
                 message
             };
-            _builder.WriteMessage(formThread);
+            _builder.WriteMessage(formThread);*/
         }
 
         private void RotateDisplay()
         {
-            var width = int.Parse(_packet.Args[0].ToString());
+            /*var width = int.Parse(_packet.Args[0].ToString());
             var height = int.Parse(_packet.Args[1].ToString());
             var angle = int.Parse(_packet.Args[2].ToString());
             var device = _packet.Args[3].ToString();
            var message = Display.Rotate(angle, width, height, device);
             var formThread = new
             {
                 message
             };
-            _builder.WriteMessage(formThread);
+            _builder.WriteMessage(formThread);*/
         }
 
         private void ChangeScreenResolution()
         {
 
-            var width = int.Parse(_packet.Args[0].ToString());
+            /*var width = int.Parse(_packet.Args[0].ToString());
             var height = int.Parse(_packet.Args[1].ToString());
             var bbp = int.Parse(_packet.Args[2].ToString());
             var freq = int.Parse(_packet.Args[3].ToString());
             var device = _packet.Args[4].ToString();
             var message = Display.ChangeResolution(device, width, height, bbp, freq);
             var formThread = new
             {
                 message
             };
-            _builder.WriteMessage(formThread);
+            _builder.WriteMessage(formThread);*/
         }
     }
 }
\ No newline at end of file
diff --git a/RemoteTaskServer/Api/Network/PacketHandlers/FilePacketHandler.cs b/RemoteTaskServer/Api/Network/PacketHandlers/FilePacketHandler.cs
index 4e742bd..8f83fb7 100644
--- a/RemoteTaskServer/Api/Network/PacketHandlers/FilePacketHandler.cs
+++ b/RemoteTaskServer/Api/Network/PacketHandlers/FilePacketHandler.cs
@@ -4,13 +4,13 @@ using System;
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.IO;
 using System.Linq;
 using System.Text;
-using AgentInterface.Settings;
 using UlteriusServer.Api.Network.Messages;
 using UlteriusServer.Api.Services.Network;
+using UlteriusServer.Utilities;
 using UlteriusServer.Utilities.Extensions;
 using UlteriusServer.Utilities.Files;
 using UlteriusServer.Utilities.Security;
 using UlteriusServer.WebSocketAPI.Authentication;
 using vtortola.WebSockets;
diff --git a/RemoteTaskServer/Api/Network/PacketHandlers/GpuPacketHandler.cs b/RemoteTaskServer/Api/Network/PacketHandlers/GpuPacketHandler.cs
index 388d2f0..c4fab49 100644
--- a/RemoteTaskServer/Api/Network/PacketHandlers/GpuPacketHandler.cs
+++ b/RemoteTaskServer/Api/Network/PacketHandlers/GpuPacketHandler.cs
@@ -1,11 +1,10 @@
 ﻿#region
 
 using System.Linq;
 using System.Management;
 using System.Runtime.ExceptionServices;
-using AgentInterface.Api.System;
 using UlteriusServer.Api.Network.Messages;
 using UlteriusServer.Api.Network.Models;
 using UlteriusServer.WebSocketAPI.Authentication;
 using vtortola.WebSockets;
 using static UlteriusServer.Api.Network.PacketManager;
@@ -52,13 +51,11 @@ namespace UlteriusServer.Api.Network.PacketHandlers
         //random crash happening in this DLL, will fork and fix.
         [HandleProcessCorruptedStateExceptions]
         private float? GetGpuTemp(string gpuName)
         {
 
-            return UlteriusApiServer.RunningAsService
-                ? UlteriusApiServer.AgentClient.GetGpuTemp(gpuName)
-                : SystemData.GetGpuTemp(gpuName);
+            return SystemData.GetGpuTemp(gpuName);
         }
 
 
         public override void HandlePacket(Packet packet)
         {
diff --git a/RemoteTaskServer/Api/Network/PacketHandlers/ProcessPacketHandler.cs b/RemoteTaskServer/Api/Network/PacketHandlers/ProcessPacketHandler.cs
index 00a868e..a8565ad 100644
--- a/RemoteTaskServer/Api/Network/PacketHandlers/ProcessPacketHandler.cs
+++ b/RemoteTaskServer/Api/Network/PacketHandlers/ProcessPacketHandler.cs
@@ -5,13 +5,13 @@ using System.Collections.Generic;
 using System.Diagnostics;
 using System.Drawing.Imaging;
 using System.IO;
 using System.Linq;
 using System.Threading.Tasks;
-using AgentInterface.Api.Win32;
 using UlteriusServer.Api.Network.Messages;
 using UlteriusServer.Api.Network.Models;
+using UlteriusServer.Api.Win32;
 using UlteriusServer.Utilities;
 using UlteriusServer.WebSocketAPI.Authentication;
 using vtortola.WebSockets;
 
 #endregion
@@ -31,33 +31,14 @@ namespace UlteriusServer.Api.Network.PacketHandlers
             var path = _packet.Args[0].ToString();
             bool processStarted;
             var processId = -1;
             try
             {
-                if (Environment.UserName.Equals("SYSTEM") && Tools.RunningPlatform() == Tools.Platform.Windows)
-                {
-                    var task = Task.Run(() =>
-                    {
-                        try
-                        {
-                            ProcessStarter.PROCESS_INFORMATION procInfo;
-                            ProcessStarter.StartProcessAndBypassUAC(path,  out procInfo);
-                        }
-                        catch (Exception)
-                        {
-                            //continue
-                        }
-                    });
-                    processStarted = task.Wait(TimeSpan.FromSeconds(5));
-                }
-                else
-                {
-                    var processStartInfo = new ProcessStartInfo(path);
-                    var process = new Process {StartInfo = processStartInfo};
-                    processStarted = process.Start();
-                    processId = process.Id;
-                }
+                var processStartInfo = new ProcessStartInfo(path);
+                var process = new Process { StartInfo = processStartInfo };
+                processStarted = process.Start();
+                processId = process.Id;
             }
             catch (Exception ex)
             {
                 Console.WriteLine(ex.Message);
                 processStarted = false;
diff --git a/RemoteTaskServer/Api/Network/PacketHandlers/ScreenSharePacketHandler.cs b/RemoteTaskServer/Api/Network/PacketHandlers/ScreenSharePacketHandler.cs
index 0cacf9e..69921a7 100644
--- a/RemoteTaskServer/Api/Network/PacketHandlers/ScreenSharePacketHandler.cs
+++ b/RemoteTaskServer/Api/Network/PacketHandlers/ScreenSharePacketHandler.cs
@@ -8,14 +8,14 @@ using System.Linq;
 using System.Runtime.InteropServices;
 using System.Threading;
 using System.Windows.Forms;
 using WindowsInput;
 using WindowsInput.Native;
-using AgentInterface.Api.ScreenShare;
-using AgentInterface.Api.ScreenShare.DesktopDuplication;
-using AgentInterface.Api.Win32;
 using UlteriusServer.Api.Network.Messages;
+using UlteriusServer.Api.Win32;
+using UlteriusServer.Api.Win32.ScreenShare;
+using UlteriusServer.Api.Win32.ScreenShare.DesktopDuplication;
 using UlteriusServer.WebSocketAPI.Authentication;
 using vtortola.WebSockets;
 using static UlteriusServer.Api.UlteriusApiServer;
 using ScreenShareService = UlteriusServer.Api.Services.LocalSystem.ScreenShareService;
 using SystemInformation = UlteriusServer.Api.Network.Models.SystemInformation;
@@ -123,13 +123,11 @@ namespace UlteriusServer.Api.Network.PacketHandlers
                     };
                     _builder.WriteMessage(failData);
                     return;
                 }
                 _authClient.ShutDownScreenShare = false;
-                var stream = RunningAsService
-                    ? new Thread(GetScreenAgentFrame) { IsBackground = true }
-                    : new Thread(GetScreenFrame) { IsBackground = true };
+                var stream = new Thread(GetScreenFrame) { IsBackground = true };
                 ScreenShareService.Streams[_authClient] = stream;
                 var data = new
                 {
                     screenStreamStarted = true
                 };
@@ -146,45 +144,10 @@ namespace UlteriusServer.Api.Network.PacketHandlers
 
                 _builder.WriteMessage(data);
             }
         }
 
-
-        private void GetScreenAgentFrame()
-        {
-            try
-            {
-                while (_client != null && _client.IsConnected && _authClient != null &&
-                       !_authClient.ShutDownScreenShare)
-                {
-                    try
-                    {
-                        var image = AgentClient.GetCleanFrame();
-                        if (image != null)
-                        {
-                            if (image.UsingGpu)
-                            {
-                                SendGpuFrame(image.FinishedRegions);
-                            }
-                            else
-                            {
-                                SendPolledFrame(image.ScreenImage, image.Bounds);
-                            }
-                        }
-                    }
-                    catch (Exception e)
-                    {
-                        //  Console.WriteLine(e.Message + " " + e.StackTrace);
-                    }
-                }
-                Console.WriteLine("Screen Share Died");
-            }
-            catch (Exception)
-            {
-            }
-        }
-
         private void SendGpuFrame(FinishedRegions[] gpuFrame)
         {
             if (gpuFrame == null)
             {
                 return;
@@ -206,10 +169,14 @@ namespace UlteriusServer.Api.Network.PacketHandlers
         private void GetScreenFrame()
         {
             while (_client != null && _client.IsConnected && _authClient != null &&
                    !_authClient.ShutDownScreenShare)
             {
+                if (RunningAsService && DesktopWatcher.CurrentDesktop != null)
+                {
+                    Desktop.SetCurrent(DesktopWatcher.CurrentDesktop);
+                }
                 try
                 {
                     var image = ScreenData.DesktopCapture();
                     if (image == null) continue;
                     if (image.UsingGpu)
@@ -241,10 +208,14 @@ namespace UlteriusServer.Api.Network.PacketHandlers
         }
 
 
         public override void HandlePacket(Packet packet)
         {
+            if (RunningAsService && DesktopWatcher.CurrentDesktop != null)
+            {
+                Desktop.SetCurrent(DesktopWatcher.CurrentDesktop);
+            }
             _client = packet.Client;
             _authClient = packet.AuthClient;
             _packet = packet;
             _builder = new MessageBuilder(_authClient, _client, _packet.EndPointName, _packet.SyncKey);
             switch (_packet.EndPoint)
@@ -274,18 +245,11 @@ namespace UlteriusServer.Api.Network.PacketHandlers
                     break;
                 case PacketManager.EndPoints.KeyUp:
                     HandleKeyUp();
                     break;
                 case PacketManager.EndPoints.FullFrame:
-                    if (RunningAsService)
-                    {
-                        HandleAgentFullFrame();
-                    }
-                    else
-                    {
-                        HandleFullFrame();
-                    }
+                    HandleFullFrame();
                     break;
                 case PacketManager.EndPoints.RightClick:
                     HandleRightClick();
                     break;
                 case PacketManager.EndPoints.SetActiveMonitor:
@@ -314,72 +278,16 @@ namespace UlteriusServer.Api.Network.PacketHandlers
             SendSAS(false);
         }
 
         private void RightUp()
         {
-            if (!ScreenShareService.Streams.ContainsKey(_authClient)) return;
-            if (RunningAsService)
-            {
-                AgentClient.HandleRightMouseUp();
-            }
-            else
-            {
-                new InputSimulator().Mouse.RightButtonUp();
-            }
+            new InputSimulator().Mouse.RightButtonUp();
         }
 
         private void RightDown()
         {
-            if (!ScreenShareService.Streams.ContainsKey(_authClient)) return;
-            if (RunningAsService)
-            {
-                AgentClient.HandleRightMouseDown();
-            }
-            else
-            {
-                new InputSimulator().Mouse.RightButtonDown();
-            }
-        }
-
-        private void HandleAgentFullFrame()
-        {
-            try
-            {
-                var fullFrameData = AgentClient.GetFullFrame();
-                if (fullFrameData?.ScreenImage == null) throw new InvalidOperationException("Frame was null");
-                var bounds = fullFrameData.Bounds;
-                var image = ScreenData.ImageToByteArray(fullFrameData.ScreenImage);
-                var frameData = new
-                {
-                    screenBounds = new
-                    {
-                        top = bounds.Top,
-                        bottom = bounds.Bottom,
-                        left = bounds.Left,
-                        right = bounds.Right,
-                        height = bounds.Height,
-                        width = bounds.Width,
-                        x = bounds.X,
-                        y = bounds.Y,
-                        empty = bounds.IsEmpty,
-                        location = bounds.Location,
-                        size = bounds.Size
-                    },
-                    frameData = image.Select(b => (int)b).ToArray()
-                };
-                _builder.WriteMessage(frameData);
-            }
-            catch (Exception ex)
-            {
-                var data = new
-                {
-                    frameFailed = true,
-                    message = ex.Message
-                };
-                Console.WriteLine(ex.Message + "Fuck");
-                _builder.WriteMessage(data);
-            }
+            new InputSimulator().Mouse.RightButtonDown();
         }
 
         private void HandleFullFrame()
         {
             using (var grab = ScreenData.CaptureDesktop())
@@ -425,30 +333,22 @@ namespace UlteriusServer.Api.Network.PacketHandlers
             }
         }
 
         private void HandleKeyUp()
         {
-            if (!ScreenShareService.Streams.ContainsKey(_authClient)) return;
             var keyCodes = ((IEnumerable)_packet.Args[0]).Cast<object>()
                 .Select(x => x.ToString())
                 .ToList();
             var codes =
                 keyCodes.Select(code => ToHex(int.Parse(code.ToString())))
                     .Select(hexString => Convert.ToInt32(hexString, 16))
                     .ToList();
 
-            if (RunningAsService)
-            {
-                AgentClient.HandleKeyUp(codes);
-            }
-            else
+            foreach (var code in codes)
             {
-                foreach (var code in codes)
-                {
-                    var virtualKey = (VirtualKeyCode)code;
-                    new InputSimulator().Keyboard.KeyUp(virtualKey);
-                }
+                var virtualKey = (VirtualKeyCode)code;
+                new InputSimulator().Keyboard.KeyUp(virtualKey);
             }
         }
 
 
         private string ToHex(int value)
@@ -456,47 +356,31 @@ namespace UlteriusServer.Api.Network.PacketHandlers
             return $"0x{value:X}";
         }
 
         private void HandleKeyDown()
         {
-            if (!ScreenShareService.Streams.ContainsKey(_authClient)) return;
             var keyCodes = ((IEnumerable)_packet.Args[0]).Cast<object>()
                 .Select(x => x.ToString())
                 .ToList();
             var codes =
                 keyCodes.Select(code => ToHex(int.Parse(code.ToString())))
                     .Select(hexString => Convert.ToInt32(hexString, 16))
                     .ToList();
-            if (RunningAsService)
+            foreach (var code in codes)
             {
-                AgentClient.HandleKeyDown(codes);
-            }
-            else
-            {
-                foreach (var code in codes)
-                {
-                    var virtualKey = (VirtualKeyCode)code;
-                    new InputSimulator().Keyboard.KeyDown(virtualKey);
-                }
+                var virtualKey = (VirtualKeyCode)code;
+                new InputSimulator().Keyboard.KeyDown(virtualKey);
             }
         }
 
         private void HandleScroll()
         {
-            if (!ScreenShareService.Streams.ContainsKey(_authClient)) return;
             var delta = Convert.ToInt32(_packet.Args[0], CultureInfo.InvariantCulture);
             delta = ~delta;
             var positive = delta > 0;
             var direction = positive ? 10 : -10;
-            if (RunningAsService)
-            {
-                AgentClient.ScrollMouse(positive);
-            }
-            else
-            {
-                new InputSimulator().Mouse.VerticalScroll(direction);
-            }
+            new InputSimulator().Mouse.VerticalScroll(direction);
         }
 
         private static Point Translate(Point point, Size from, Size to)
         {
             return new Point(point.X * to.Width / from.Width, point.Y * to.Height / from.Height);
@@ -508,79 +392,38 @@ namespace UlteriusServer.Api.Network.PacketHandlers
             return new Point(absoluteCoordinates.X - screen.Bounds.Left, absoluteCoordinates.Y - screen.Bounds.Top);
         }
 
         private void HandleMoveMouse()
         {
-            if (!ScreenShareService.Streams.ContainsKey(_authClient)) return;
             try
             {
 
                 int y = Convert.ToInt16(_packet.Args[0], CultureInfo.InvariantCulture);
                 int x = Convert.ToInt16(_packet.Args[1], CultureInfo.InvariantCulture);
-
-                if (RunningAsService)
-                {
-
-                    AgentClient.MoveMouse(x, y);
-                }
-                else
-                {
-                    var bounds = Display.GetWindowRectangle();
-                    x = checked((int)Math.Round(x * (65535 / (double)bounds.Width)));
-                    y = checked((int)Math.Round(y * (65535 / (double)bounds.Height)));
-                    new InputSimulator().Mouse.MoveMouseTo(x, y);
-                }
+                var bounds = Display.GetWindowRectangle();
+                x = checked((int)Math.Round(x * (65535 / (double)bounds.Width)));
+                y = checked((int)Math.Round(y * (65535 / (double)bounds.Height)));
+                new InputSimulator().Mouse.MoveMouseTo(x, y);
             }
 
             catch
             {
-                Console.WriteLine("Error moving mouse");
+                //Console.WriteLine("Error moving mouse");
             }
         }
 
         private void HandleRightClick()
         {
-            if (ScreenShareService.Streams.ContainsKey(_authClient))
-            {
-                if (RunningAsService)
-                {
-                    AgentClient.HandleRightClick();
-                }
-                else
-                {
-                    new InputSimulator().Mouse.RightButtonClick();
-                }
-            }
+            new InputSimulator().Mouse.RightButtonClick();
         }
 
         private void HandleMouseUp()
         {
-            if (ScreenShareService.Streams.ContainsKey(_authClient))
-            {
-                if (RunningAsService)
-                {
-                    AgentClient.HandleLeftMouseUp();
-                }
-                else
-                {
-                    new InputSimulator().Mouse.LeftButtonUp();
-                }
-            }
+            new InputSimulator().Mouse.LeftButtonUp();
         }
 
         private void HandleMouseDown()
         {
-            if (ScreenShareService.Streams.ContainsKey(_authClient))
-            {
-                if (RunningAsService)
-                {
-                    AgentClient.HandleLeftMouseDown();
-                }
-                else
-
-                {
-                    new InputSimulator().Mouse.LeftButtonDown();
-                }
-            }
+            new InputSimulator().Mouse.LeftButtonDown();
         }
     }
 }
\ No newline at end of file
diff --git a/RemoteTaskServer/Api/Network/PacketHandlers/ServerPacketHandler.cs b/RemoteTaskServer/Api/Network/PacketHandlers/ServerPacketHandler.cs
index aad95d1..e1fce93 100644
--- a/RemoteTaskServer/Api/Network/PacketHandlers/ServerPacketHandler.cs
+++ b/RemoteTaskServer/Api/Network/PacketHandlers/ServerPacketHandler.cs
@@ -6,12 +6,12 @@ using System.Diagnostics;
 using System.IO;
 using System.Linq;
 using System.Reflection;
 using System.Text;
 using System.Windows.Forms;
-using AgentInterface.Settings;
 using UlteriusServer.Api.Network.Messages;
+using UlteriusServer.Utilities;
 using UlteriusServer.Utilities.Security;
 using UlteriusServer.WebSocketAPI.Authentication;
 using vtortola.WebSockets;
 
 #endregion
diff --git a/RemoteTaskServer/Api/Network/PacketHandlers/SettingsPacketHandler.cs b/RemoteTaskServer/Api/Network/PacketHandlers/SettingsPacketHandler.cs
index be097e3..494706a 100644
--- a/RemoteTaskServer/Api/Network/PacketHandlers/SettingsPacketHandler.cs
+++ b/RemoteTaskServer/Api/Network/PacketHandlers/SettingsPacketHandler.cs
@@ -1,13 +1,13 @@
 ﻿#region
 
 using System;
 using System.IO;
 using System.Text;
-using AgentInterface.Settings;
 using Newtonsoft.Json;
 using UlteriusServer.Api.Network.Messages;
+using UlteriusServer.Utilities;
 using UlteriusServer.WebSocketAPI.Authentication;
 using vtortola.WebSockets;
 
 #endregion
 
diff --git a/RemoteTaskServer/Api/Network/UlteriusAgentClient.cs b/RemoteTaskServer/Api/Network/UlteriusAgentClient.cs
deleted file mode 100644
index 9e765a8..0000000
--- a/RemoteTaskServer/Api/Network/UlteriusAgentClient.cs
+++ /dev/null
@@ -1,313 +0,0 @@
-﻿#region
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Net.Security;
-using System.ServiceModel;
-using System.Threading;
-using System.Threading.Tasks;
-using AgentInterface;
-using AgentInterface.Api.Models;
-using UlteriusServer.Utilities;
-
-#endregion
-
-namespace UlteriusServer.Api.Network
-{
-    public class UlteriusAgentClient
-    {
-        private IInputContract InputChannel { get; set; }
-
-        private IFrameContract FrameChannel { get; set; }
-
-        public void Start(bool keepAlive = true)
-        {
-            var inputAddress = "net.tcp://localhost/ulterius/agent/input/";
-            var frameAddress = "net.pipe://localhost/ulterius/agent/frames/";
-
-            var inputBinding = new NetTcpBinding
-            {
-                Security = new NetTcpSecurity
-                {
-                    Transport = { ProtectionLevel = ProtectionLevel.None },
-                    Mode = SecurityMode.None
-                },
-                MaxReceivedMessageSize = int.MaxValue
-            };
-            var ep = new EndpointAddress(inputAddress);
-            
-            InputChannel = ChannelFactory<IInputContract>.CreateChannel(inputBinding, ep);
-         
-
-            var frameBinding = new NetNamedPipeBinding
-            {
-                Security = new NetNamedPipeSecurity
-                {
-                    Transport = { ProtectionLevel = ProtectionLevel.None },
-                    Mode = NetNamedPipeSecurityMode.None
-                },
-                MaxReceivedMessageSize = int.MaxValue
-            };
-            var epf = new EndpointAddress(frameAddress);
-            FrameChannel = ChannelFactory<IFrameContract>.CreateChannel(frameBinding, epf);
-
-
-            if (!keepAlive) return;
-            var task = new Task(KeepAlive);
-            task.Start();
-        }
-
-        private void KeepAlive()
-        {
-            while (true)
-            {
-                Tools.RestartDaemon();
-                var alive = ChannelActive();
-                if (!alive)
-                {
-                    var agentList = Process.GetProcessesByName("UlteriusAgent");
-                    if (agentList.Length == 0)
-                    {
-                        Tools.RestartAgent();
-                    }
-                    Start(false);
-                }
-                Thread.Sleep(1000);
-            }
-        }
-
-        public void ScrollMouse(bool positive)
-        {
-            try
-            {
-                InputChannel?.MouseScroll(positive);
-            }
-            catch (EndpointNotFoundException)
-            {
-                //
-            }
-            catch (CommunicationException)
-            {
-                //
-            }
-        }
-
-        public bool ChannelActive()
-        {
-            try
-            {
-                return FrameChannel != null && FrameChannel.KeepAlive();
-            }
-            catch (EndpointNotFoundException)
-            {
-                return false;
-            }
-            catch (CommunicationException)
-            {
-                return false;
-            }
-        }
-
-        public FrameInformation GetCleanFrame()
-        {
-            try
-            {
-                return FrameChannel.GetCleanFrame();
-            }
-            catch (EndpointNotFoundException)
-            {
-                return null;
-            }
-            catch (TimeoutException)
-            {
-                return null;
-            }
-            catch (CommunicationException)
-            {
-                return null;
-            }
-        }
-
-        public FrameInformation GetFullFrame()
-        {
-            try
-            {
-                return FrameChannel.GetFullFrame();
-            }
-            catch (EndpointNotFoundException)
-            {
-                return null;
-            }
-            catch (CommunicationException)
-            {
-                return null;
-            }
-        }
-
-        public void HandleRightMouseDown()
-        {
-            try
-            {
-                InputChannel.HandleRightMouseDown();
-            }
-            catch (EndpointNotFoundException)
-            {
-            }
-            catch (CommunicationException)
-            {
-            }
-        }
-
-        public void HandleRightMouseUp()
-        {
-            try
-            {
-                InputChannel.HandleRightMouseUp();
-            }
-            catch (EndpointNotFoundException)
-            {
-            }
-            catch (CommunicationException)
-            {
-            }
-        }
-
-        public void MoveMouse(int x, int y)
-        {
-            try
-            {
-                InputChannel.MoveMouse(x, y);
-            }
-            catch (EndpointNotFoundException)
-            {
-            }
-            catch (CommunicationException ex)
-            {
-                Console.WriteLine(ex.Message);
-                Console.Write(ex.StackTrace);
-            }
-        }
-
-        public void HandleLeftMouseDown()
-        {
-            try
-            {
-                InputChannel.HandleLeftMouseDown();
-            }
-            catch (EndpointNotFoundException)
-            {
-            }
-            catch (CommunicationException)
-            {
-            }
-        }
-
-        public void HandleLeftMouseUp()
-        {
-            try
-            {
-                InputChannel.HandleLeftMouseUp();
-            }
-            catch (EndpointNotFoundException)
-            {
-            }
-            catch (CommunicationException)
-            {
-            }
-        }
-
-        public void HandleKeyDown(List<int> keyCodes)
-        {
-            try
-            {
-                InputChannel.HandleKeyDown(keyCodes);
-            }
-            catch (EndpointNotFoundException)
-            {
-            }
-            catch (CommunicationException)
-            {
-            }
-        }
-
-        public void HandleKeyUp(List<int> keyCodes)
-        {
-            try
-            {
-                InputChannel.HandleKeyUp(keyCodes);
-            }
-            catch (EndpointNotFoundException)
-            {
-            }
-            catch (CommunicationException)
-            {
-            }
-        }
-
-        public void HandleRightClick()
-        {
-            try
-            {
-                InputChannel.HandleRightClick();
-            }
-            catch (EndpointNotFoundException)
-            {
-            }
-            catch (CommunicationException)
-            {
-            }
-        }
-
-        public float GetGpuTemp(string gpuName)
-        {
-            try
-            {
-                var temp = InputChannel.GetGpuTemp(gpuName);
-                return temp;
-            }
-            catch (EndpointNotFoundException)
-            {
-                return -1;
-            }
-            catch (CommunicationException)
-            {
-                return -1;
-            }
-        }
-
-        public List<DisplayInformation> GetDisplayInformation()
-        {
-            try
-            {
-                return InputChannel.GetDisplayInformation();
-            }
-            catch (EndpointNotFoundException)
-            {
-                return null;
-            }
-            catch (CommunicationException)
-            {
-                return null;
-            }
-        }
-
-        public List<float> GetCpuTemps()
-        {
-            try
-            {
-                return InputChannel.GetCpuTemps();
-            }
-            catch (EndpointNotFoundException)
-            {
-                return null;
-            }
-            catch (CommunicationException)
-            {
-                return null;
-            }
-        }
-
-
-    }
-}
\ No newline at end of file
diff --git a/RemoteTaskServer/Api/Services/LocalSystem/SystemService.cs b/RemoteTaskServer/Api/Services/LocalSystem/SystemService.cs
index 46e1918..019dd61 100644
--- a/RemoteTaskServer/Api/Services/LocalSystem/SystemService.cs
+++ b/RemoteTaskServer/Api/Services/LocalSystem/SystemService.cs
@@ -11,16 +11,17 @@ using System.Net.NetworkInformation;
 using System.Runtime.InteropServices;
 using System.Security.Principal;
 using System.Text.RegularExpressions;
 using System.Threading;
 using System.Threading.Tasks;
-using AgentInterface.Api.Models;
-using AgentInterface.Api.System;
+using System.Windows.Forms;
 using UlteriusServer.Api.Network.Models;
 using UlteriusServer.Api.Services.Network;
+using UlteriusServer.Api.Win32;
+using UlteriusServer.Api.Win32.ScreenShare.Models;
 using UlteriusServer.Utilities.Drive;
-using static AgentInterface.Api.Win32.Display;
+using SystemInformation = UlteriusServer.Api.Network.Models.SystemInformation;
 
 #endregion
 
 namespace UlteriusServer.Api.Services.LocalSystem
 {
@@ -197,22 +198,35 @@ namespace UlteriusServer.Api.Services.LocalSystem
             }
         }
 
         private List<DisplayInformation> GetDisplayInformation()
         {
-            var displayList = DisplayInformation();
-            if (!UlteriusApiServer.RunningAsService) return displayList;
-            var displayInfo = UlteriusApiServer.AgentClient.GetDisplayInformation();
-            return displayInfo ?? displayList;
+            var displays = new List<DisplayInformation>();
+            for (var i = 0; i < Screen.AllScreens.Length; i++)
+            {
+                var friendly = Display.GetDeviceFriendlyName(i);
+                var display = new DisplayInformation {FriendlyName = friendly};
+                var currentScreen = Screen.AllScreens[i];
+                display.CurrentResolution = new ResolutionInformation
+                {
+                    BitsPerPixel = currentScreen.BitsPerPixel,
+                    Frequency = 60,
+                    Height = currentScreen.Bounds.Height,
+                    Width = currentScreen.Bounds.Width,
+                    Orientation = "Unknown",
+                    X = currentScreen.Bounds.X,
+                    Y = currentScreen.Bounds.Y
+                };
+                displays.Add(display);
+            }
+            return displays;
         }
 
       
         private List<float> GetCpuTemps()
         {
-            return UlteriusApiServer.RunningAsService
-                ? UlteriusApiServer.AgentClient.GetCpuTemps()
-                : SystemData.GetCpuTemps();
+            return SystemData.GetCpuTemps();
         }
 
 
         public string GetMotherBoard()
         {
@@ -229,29 +243,29 @@ namespace UlteriusServer.Api.Services.LocalSystem
                 catch
                 {
                     _motherBoard = "Board Unknown";
                 }
             }
-            return _motherBoard;
+            return string.IsNullOrEmpty(_motherBoard) ? "Board Unknown" : _motherBoard;
         }
 
 
         private static object GetNetworkInfo()
         {
             long totalBytesReceived = 0;
             long totalBytesSent = 0;
 
             foreach (var networkInterface in NetworkInterface.GetAllNetworkInterfaces())
             {
-                totalBytesReceived += networkInterface.GetIPv4Statistics().BytesReceived;
-                totalBytesSent += networkInterface.GetIPv4Statistics().BytesSent;
+                totalBytesReceived += networkInterface?.GetIPv4Statistics()?.BytesReceived ?? 0;
+                totalBytesSent += networkInterface?.GetIPv4Statistics()?.BytesSent ?? 0;
             }
 
 
             var data = new
             {
-                totalNetworkInterfaces = NetworkInterface.GetAllNetworkInterfaces().Length,
+                totalNetworkInterfaces = NetworkInterface.GetAllNetworkInterfaces()?.Length ?? 0,
                 networkInterfaces = NetworkInterface.GetAllNetworkInterfaces(),
                 totalBytesReceived,
                 totalBytesSent
             };
 
diff --git a/RemoteTaskServer/Api/Services/Network/NetworkService.cs b/RemoteTaskServer/Api/Services/Network/NetworkService.cs
index e095a25..8b4fce9 100644
--- a/RemoteTaskServer/Api/Services/Network/NetworkService.cs
+++ b/RemoteTaskServer/Api/Services/Network/NetworkService.cs
@@ -5,11 +5,11 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Net;
 using System.Net.NetworkInformation;
 using System.Net.Sockets;
 using System.Runtime.InteropServices;
-using AgentInterface.Settings;
+using UlteriusServer.Utilities;
 
 #endregion
 
 namespace UlteriusServer.Api.Services.Network
 {
diff --git a/RemoteTaskServer/Api/Services/Update/UpdateService.cs b/RemoteTaskServer/Api/Services/Update/UpdateService.cs
index 76bead6..018f1fb 100644
--- a/RemoteTaskServer/Api/Services/Update/UpdateService.cs
+++ b/RemoteTaskServer/Api/Services/Update/UpdateService.cs
@@ -1,14 +1,15 @@
 ﻿#region
 
 using System;
+using System.Diagnostics;
 using System.IO;
 using System.Net.Http;
 using System.Reflection;
 using System.Text.RegularExpressions;
 using System.Threading.Tasks;
-using AgentInterface.Api.Win32;
+using UlteriusServer.Api.Win32;
 using UlteriusServer.Utilities;
 
 #endregion
 
 namespace UlteriusServer.Api.Services.Update
@@ -50,14 +51,12 @@ namespace UlteriusServer.Api.Services.Update
             }
         }
 
         private void CheckForServerUpdates()
         {
-            var file = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
-                 "Ulterius Updater.exe /silentall -nofreqcheck");
-            ProcessStarter.PROCESS_INFORMATION procInfo;
-            ProcessStarter.StartProcessAndBypassUAC(file,  out procInfo);
+            var file = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Ulterius Updater.exe /silentall -nofreqcheck");
+            Process.Start(file);
         }
 
 
         private async Task<bool> DownloadUpdate()
         {
diff --git a/AgentInterface/Api/System/SystemData.cs b/RemoteTaskServer/Api/SystemData.cs
similarity index 70%
rename from AgentInterface/Api/System/SystemData.cs
rename to RemoteTaskServer/Api/SystemData.cs
index db38aa8..48fd0c0 100644
--- a/AgentInterface/Api/System/SystemData.cs
+++ b/RemoteTaskServer/Api/SystemData.cs
@@ -1,99 +1,99 @@
-﻿using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Runtime.ExceptionServices;
-using OpenHardwareMonitor.Hardware;
-
-namespace AgentInterface.Api.System
-{
-   public  class SystemData
-    {
-
-        [HandleProcessCorruptedStateExceptions]
-        public static float GetGpuTemp(string gpuName)
-        {
-            try
-            {
-                var myComputer = new Computer();
-                myComputer.Open();
-                //possible fix for gpu temps on laptops
-                myComputer.GPUEnabled = true;
-                float temp = -1;
-                foreach (var hardwareItem in myComputer.Hardware)
-                {
-                    hardwareItem.Update();
-                    switch (hardwareItem.HardwareType)
-                    {
-                        case HardwareType.GpuNvidia:
-                            foreach (
-                                var sensor in
-                                    hardwareItem.Sensors.Where(
-                                        sensor =>
-                                            sensor.SensorType == SensorType.Temperature &&
-                                            hardwareItem.Name.Contains(gpuName)))
-                            {
-                                if (sensor.Value != null)
-                                {
-                                    temp = (float)sensor.Value;
-                                }
-                            }
-                            break;
-                        case HardwareType.GpuAti:
-                            foreach (
-                                var sensor in
-                                    hardwareItem.Sensors.Where(
-                                        sensor =>
-                                            sensor.SensorType == SensorType.Temperature &&
-                                            hardwareItem.Name.Contains(gpuName)))
-                            {
-                                if (sensor.Value != null)
-                                {
-                                    temp = (float)sensor.Value;
-                                }
-                            }
-                            break;
-                    }
-                }
-                myComputer.Close();
-                return temp;
-            }
-            catch (AccessViolationException)
-            {
-                return -1;
-            }
-        }
-
-        public static List<float> GetCpuTemps()
-        {
-            var myComputer = new Computer();
-            myComputer.Open();
-            myComputer.CPUEnabled = true;
-            var tempTemps = new List<float>();
-            var procCount = Environment.ProcessorCount;
-            for (var i = 0; i < procCount; i++)
-            {
-                tempTemps.Add(-1);
-            }
-            try
-            {
-                var temps = (from hardwareItem in myComputer.Hardware
-                             where hardwareItem.HardwareType == HardwareType.CPU
-                             from sensor in hardwareItem.Sensors
-                             where sensor.SensorType == SensorType.Temperature
-                             let value = sensor.Value
-                             where value != null
-                             where value != null
-                             select (float)value).ToList();
-                if (temps.Count != 0) return temps;
-                myComputer.Close();
-                return tempTemps;
-            }
-            catch (Exception)
-            {
-                myComputer.Close();
-                return tempTemps;
-            }
-        }
-
-    }
-}
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.ExceptionServices;
+using OpenHardwareMonitor.Hardware;
+
+namespace UlteriusServer.Api
+{
+    public class SystemData
+    {
+
+        [HandleProcessCorruptedStateExceptions]
+        public static float GetGpuTemp(string gpuName)
+        {
+            try
+            {
+                var myComputer = new Computer();
+                myComputer.Open();
+                //possible fix for gpu temps on laptops
+                myComputer.GPUEnabled = true;
+                float temp = -1;
+                foreach (var hardwareItem in myComputer.Hardware)
+                {
+                    hardwareItem.Update();
+                    switch (hardwareItem.HardwareType)
+                    {
+                        case HardwareType.GpuNvidia:
+                            foreach (
+                                var sensor in
+                                hardwareItem.Sensors.Where(
+                                    sensor =>
+                                        sensor.SensorType == SensorType.Temperature &&
+                                        hardwareItem.Name.Contains(gpuName)))
+                            {
+                                if (sensor.Value != null)
+                                {
+                                    temp = (float)sensor.Value;
+                                }
+                            }
+                            break;
+                        case HardwareType.GpuAti:
+                            foreach (
+                                var sensor in
+                                hardwareItem.Sensors.Where(
+                                    sensor =>
+                                        sensor.SensorType == SensorType.Temperature &&
+                                        hardwareItem.Name.Contains(gpuName)))
+                            {
+                                if (sensor.Value != null)
+                                {
+                                    temp = (float)sensor.Value;
+                                }
+                            }
+                            break;
+                    }
+                }
+                myComputer.Close();
+                return temp;
+            }
+            catch (AccessViolationException)
+            {
+                return -1;
+            }
+        }
+
+        public static List<float> GetCpuTemps()
+        {
+            var myComputer = new Computer();
+            myComputer.Open();
+            myComputer.CPUEnabled = true;
+            var tempTemps = new List<float>();
+            var procCount = Environment.ProcessorCount;
+            for (var i = 0; i < procCount; i++)
+            {
+                tempTemps.Add(-1);
+            }
+            try
+            {
+                var temps = (from hardwareItem in myComputer.Hardware
+                    where hardwareItem.HardwareType == HardwareType.CPU
+                    from sensor in hardwareItem.Sensors
+                    where sensor.SensorType == SensorType.Temperature
+                    let value = sensor.Value
+                    where value != null
+                    where value != null
+                    select (float)value).ToList();
+                if (temps.Count != 0) return temps;
+                myComputer.Close();
+                return tempTemps;
+            }
+            catch (Exception)
+            {
+                myComputer.Close();
+                return tempTemps;
+            }
+        }
+
+    }
+}
\ No newline at end of file
diff --git a/RemoteTaskServer/Api/UlteriusApiServer.cs b/RemoteTaskServer/Api/UlteriusApiServer.cs
index 34c5ceb..07d355a 100644
--- a/RemoteTaskServer/Api/UlteriusApiServer.cs
+++ b/RemoteTaskServer/Api/UlteriusApiServer.cs
@@ -1,238 +1,256 @@
-﻿#region
-
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.IO;
-using System.Net;
-using System.Threading;
-using System.Threading.Tasks;
-using AgentInterface.Settings;
-using Newtonsoft.Json;
-using UlteriusServer.Api.Network;
-using UlteriusServer.Api.Network.Messages;
-using UlteriusServer.Api.Services.LocalSystem;
-using UlteriusServer.Api.Services.Network;
-using UlteriusServer.Api.Services.Update;
-using UlteriusServer.Forms.Utilities;
-using UlteriusServer.Utilities.Security;
-using UlteriusServer.WebSocketAPI;
-using UlteriusServer.WebSocketAPI.Authentication;
-using vtortola.WebSockets;
-using ScreenShareService = UlteriusServer.Api.Services.LocalSystem.ScreenShareService;
-
-#endregion
-
-namespace UlteriusServer.Api
-{
-    internal class UlteriusApiServer
-    {
-        public static ConcurrentDictionary<Guid, AuthClient> AllClients { get; set; }
-        public static bool RunningAsService { get; set; }
-        public static ScreenShareService ScreenShareService { get; set; }
-        public static FileSearchService FileSearchService { get; set; }
-        public static CronJobService CronJobService { get; set; }
-
-        public static UlteriusAgentClient AgentClient { get; set; }
-
-        /// <summary>
-        ///     Start the API Server
-        /// </summary>
-        public static void Start()
-        {
-            PacketLoader.LoadPackets();
-            var config = Config.Load();
-            var clientUpdateService = new UpdateService();
-            clientUpdateService.Start();
-            FileSearchService = new FileSearchService(Path.Combine(AppEnvironment.DataPath, "fileIndex.db"));
-            FileSearchService.Start();
-            CronJobService = new CronJobService(Path.Combine(AppEnvironment.DataPath, "jobs.json"), Path.Combine(AppEnvironment.DataPath, "scripts"));
-            CronJobService.ConfigureJobs();
-            var apiPort = config.TaskServer.TaskServerPort;
-            AllClients = new ConcurrentDictionary<Guid, AuthClient>();
-            ScreenShareService = new ScreenShareService();
-            var address = NetworkService.GetAddress();
-            var webCamPort = config.Webcams.WebcamPort;
-            var screenSharePort = config.ScreenShareService.ScreenSharePort;
-            var endPoints = new List<IPEndPoint>
-            {
-                new IPEndPoint(address, apiPort),
-                new IPEndPoint(address, webCamPort),
-                new IPEndPoint(address, screenSharePort)
-            };
-            var server = new WebSocketEventListener(endPoints, new WebSocketListenerOptions
-            {
-                PingTimeout = TimeSpan.FromSeconds(2),
-                NegotiationTimeout = TimeSpan.FromSeconds(2),
-                WebSocketSendTimeout = TimeSpan.FromSeconds(2),
-                WebSocketReceiveTimeout = TimeSpan.FromSeconds(2),
-                ParallelNegotiations = Environment.ProcessorCount*2,
-                NegotiationQueueCapacity = 256,
-                TcpBacklog = 1000,
-                OnHttpNegotiation = (request, response) =>
-                {
-                    if (request.Cookies["ConnectionId"] == null)
-                        response.Cookies.Add(new Cookie("ConnectionId", Guid.NewGuid().ToString()));
-                }
-            });
-            server.OnConnect += HandleConnect;
-            server.OnDisconnect += HandleDisconnect;
-            server.OnPlainTextMessage += HandlePlainTextMessage;
-            server.OnEncryptedMessage += HandleEncryptedMessage;
-            server.OnError += HandleError;
-            server.Start();
-            Log("Api Server started at " + address);
-            if (RunningAsService)
-            {
-                AgentClient = new UlteriusAgentClient();
-                AgentClient.Start();
-            }
-        }
-
-        
-
-
-        /// <summary>
-        ///     Handles encrypted binary messages
-        /// </summary>
-        /// <param name="clientSocket"></param>
-        /// <param name="message"></param>
-        private static void HandleEncryptedMessage(WebSocket clientSocket, byte[] message)
-        {
-            var connectionId = CookieManager.GetConnectionId(clientSocket);
-            AuthClient authClient;
-            if (AllClients.TryGetValue(connectionId, out authClient))
-            {
-                var packetManager = new PacketManager(authClient, clientSocket, message);
-                var packet = packetManager.GetPacket();
-                packet?.HandlePacket();
-            }
-        }
-
-        private static void HandleError(WebSocket websocket, Exception error)
-        {
-            Console.WriteLine(error.StackTrace + " " + error.Message);
-        }
-
-        /// <summary>
-        ///     Handles plaintext JSON packets.
-        /// </summary>
-        /// <param name="clientSocket"></param>
-        /// <param name="message"></param>
-        private static void HandlePlainTextMessage(WebSocket clientSocket, string message)
-        {
-            var connectionId = CookieManager.GetConnectionId(clientSocket);
-            AuthClient authClient;
-            if (AllClients.TryGetValue(connectionId, out authClient))
-            {
-                var packetManager = new PacketManager(authClient, clientSocket, message);
-                var packet = packetManager.GetPacket();
-                packet?.HandlePacket();
-            }
-        }
-
-
-        /// <summary>
-        ///     Remove a client when it disconnects
-        /// </summary>
-        /// <param name="clientSocket"></param>
-        private static void HandleDisconnect(WebSocket clientSocket)
-        {
-            var connectionId = CookieManager.GetConnectionId(clientSocket);
-            AuthClient temp = null;
-            if (AllClients.TryRemove(connectionId, out temp))
-            {
-                Console.WriteLine("Disconnection from " + clientSocket.RemoteEndpoint);
-                var userCount = AllClients.Count;
-                var extra = userCount < 1 ? "s" : string.Empty;
-                UlteriusTray.ShowMessage($"There are now {userCount} user{extra} connected.", "A user disconnected!");
-            }
-        }
-
-        /// <summary>
-        ///     When a client connects, assign them a unique RSA keypair for handshake.
-        /// </summary>
-        /// <param name="clientSocket"></param>
-        private static async void HandleConnect(WebSocket clientSocket)
-        {
-            var connectionId = CookieManager.GetConnectionId(clientSocket);
-            AuthClient authClient;
-            AllClients.TryGetValue(connectionId, out authClient);
-            if (authClient != null)
-            {
-                if (RunningAsService)
-                {
-                    MessageQueueManager agentManager;
-                    if (!authClient.MessageQueueManagers.TryGetValue(22005, out agentManager))
-                    {
-                        if (authClient.MessageQueueManagers.TryAdd(22005,
-                            new MessageQueueManager()))
-                        {
-                            Console.WriteLine("Service Manager Started");
-                        }
-                    }
-                }
-                MessageQueueManager manager;
-                //check if a manager for that port exist, if not, create one
-                if (!authClient.MessageQueueManagers.TryGetValue(clientSocket.LocalEndpoint.Port, out manager))
-                {
-                    if (authClient.MessageQueueManagers.TryAdd(clientSocket.LocalEndpoint.Port,
-                        new MessageQueueManager()))
-                    {
-                        Console.WriteLine("Manager started for " + clientSocket.LocalEndpoint.Port);
-                    }
-                }
-                return;
-            }
-            Console.WriteLine("Connection from " + clientSocket.RemoteEndpoint);
-            var rsa = new Rsa();
-            rsa.GenerateKeyPairs();
-            var client = new AuthClient
-            {
-                PublicKey = rsa.PublicKey,
-                PrivateKey = rsa.PrivateKey,
-                MessageQueueManagers = new ConcurrentDictionary<int, MessageQueueManager>()
-            };
-            client.MessageQueueManagers.TryAdd(clientSocket.LocalEndpoint.Port, new MessageQueueManager());
-            AllClients.AddOrUpdate(connectionId, client, (key, value) => value);
-            await SendWelcomeMessage(client, clientSocket);
-        }
-
-        /// <summary>
-        ///     Sends a new user their unique RSA keypair
-        /// </summary>
-        /// <param name="client"></param>
-        /// <param name="clientSocket"></param>
-        private static async Task SendWelcomeMessage(AuthClient client, WebSocket clientSocket)
-        {
-            var welcomeMessage = JsonConvert.SerializeObject(new
-            {
-                endpoint = "connectedToUlterius",
-                results = new
-                {
-                    message = "Ulterius server online!",
-                    publicKey = Rsa.SecureStringToString(client.PublicKey)
-                }
-            });
-            if (clientSocket != null)
-            {
-                try
-                {
-                    await clientSocket.WriteStringAsync(welcomeMessage, CancellationToken.None);
-                    var userCount = AllClients.Count;
-                    var extra = userCount > 1 ? "s" : string.Empty;
-                    UlteriusTray.ShowMessage($"There are now {userCount} user{extra} connected.", "A new user connected!");
-                }
-                catch (Exception ex)
-                {
-                    Console.WriteLine("Failed to write welcome message " + ex.Message );
-                }
-            }
-        }
-
-        private static void Log(string message)
-        {
-            Console.WriteLine(message);
-        }
-    }
+﻿#region
+
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.IO;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+using UlteriusServer.Api.Network;
+using UlteriusServer.Api.Network.Messages;
+using UlteriusServer.Api.Services.LocalSystem;
+using UlteriusServer.Api.Services.Network;
+using UlteriusServer.Api.Services.Update;
+using UlteriusServer.Forms.Utilities;
+using UlteriusServer.Utilities;
+using UlteriusServer.Utilities.Security;
+using UlteriusServer.WebSocketAPI;
+using UlteriusServer.WebSocketAPI.Authentication;
+using vtortola.WebSockets;
+using vtortola.WebSockets.Http;
+using ScreenShareService = UlteriusServer.Api.Services.LocalSystem.ScreenShareService;
+
+#endregion
+
+namespace UlteriusServer.Api
+{
+    internal class UlteriusApiServer
+    {
+        public static ConcurrentDictionary<Guid, AuthClient> AllClients { get; set; }
+        public static bool RunningAsService { get; set; }
+        public static ScreenShareService ScreenShareService { get; set; }
+        public static FileSearchService FileSearchService { get; set; }
+        public static CronJobService CronJobService { get; set; }
+        private static int _bufferSize = 1024 * 8;
+        private static int _bufferPoolSize;
+
+        /// <summary>
+        ///     Start the API Server
+        /// </summary>
+        public static void Start()
+        {
+            _bufferPoolSize = 100 * _bufferSize;
+            PacketLoader.LoadPackets();
+            var config = Config.Load();
+            var clientUpdateService = new UpdateService();
+            clientUpdateService.Start();
+            FileSearchService = new FileSearchService(Path.Combine(AppEnvironment.DataPath, "fileIndex.db"));
+            FileSearchService.Start();
+            CronJobService = new CronJobService(Path.Combine(AppEnvironment.DataPath, "jobs.json"), Path.Combine(AppEnvironment.DataPath, "scripts"));
+            CronJobService.ConfigureJobs();
+            var apiPort = config.TaskServer.TaskServerPort;
+            AllClients = new ConcurrentDictionary<Guid, AuthClient>();
+            ScreenShareService = new ScreenShareService();
+            var address = NetworkService.GetAddress();
+            var webCamPort = config.Webcams.WebcamPort;
+            var screenSharePort = config.ScreenShareService.ScreenSharePort;
+            var listenEndPoints = new Uri[] {
+                new Uri($"ws://{address}:{apiPort}"),
+                new Uri($"ws://{address}:{webCamPort}"),
+                new Uri($"ws://{address}:{screenSharePort}")
+            };
+            var options = new WebSocketListenerOptions
+            {
+                PingMode = PingMode.LatencyControl,
+                NegotiationTimeout = TimeSpan.FromSeconds(30),
+                PingTimeout = TimeSpan.FromSeconds(5),
+                ParallelNegotiations = 16,
+                NegotiationQueueCapacity = 256,
+                BufferManager = BufferManager.CreateBufferManager(_bufferPoolSize, _bufferSize),
+                Logger = NullLogger.Instance,
+                HttpAuthenticationHandler = async (request, response) =>
+                {
+                    await Task.Delay(TimeSpan.FromMilliseconds(1));
+                    if (request.Cookies["ConnectionId"] == null)
+                        response.Cookies.Add(new Cookie("ConnectionId", Guid.NewGuid().ToString()));
+                    return true;
+                }
+            };
+            options.Transports.ConfigureTcp(tcp =>
+            {
+                tcp.BacklogSize = 1000; // max pending connections waiting to be accepted
+                tcp.ReceiveBufferSize = _bufferSize;
+                tcp.SendBufferSize = _bufferSize;
+                tcp.LingerState = new LingerOption(true, 0);
+                tcp.NoDelay = true;
+                tcp.IsAsync = true;
+                
+                tcp.ReceiveTimeout = TimeSpan.FromSeconds(1);
+                tcp.SendTimeout = TimeSpan.FromSeconds(3);
+            });
+
+            var server = new WebSocketEventListener(listenEndPoints, options);
+            server.OnConnect += HandleConnect;
+            server.OnDisconnect += HandleDisconnect;
+            server.OnPlainTextMessage += HandlePlainTextMessage;
+            server.OnEncryptedMessage += HandleEncryptedMessage;
+            server.OnError += HandleError;
+            server.Start();
+            Log("Api Server started at " + address);
+        }
+
+        
+
+
+        /// <summary>
+        ///     Handles encrypted binary messages
+        /// </summary>
+        /// <param name="clientSocket"></param>
+        /// <param name="message"></param>
+        private static void HandleEncryptedMessage(WebSocket clientSocket, byte[] message)
+        {
+            var connectionId = CookieManager.GetConnectionId(clientSocket);
+            AuthClient authClient;
+            if (AllClients.TryGetValue(connectionId, out authClient))
+            {
+                var packetManager = new PacketManager(authClient, clientSocket, message);
+                var packet = packetManager.GetPacket();
+                packet?.HandlePacket();
+            }
+        }
+
+        private static void HandleError(WebSocket websocket, Exception error)
+        {
+            Console.WriteLine(error.StackTrace + " " + error.Message);
+        }
+
+        /// <summary>
+        ///     Handles plaintext JSON packets.
+        /// </summary>
+        /// <param name="clientSocket"></param>
+        /// <param name="message"></param>
+        private static void HandlePlainTextMessage(WebSocket clientSocket, string message)
+        {
+            var connectionId = CookieManager.GetConnectionId(clientSocket);
+            AuthClient authClient;
+            if (AllClients.TryGetValue(connectionId, out authClient))
+            {
+                var packetManager = new PacketManager(authClient, clientSocket, message);
+                var packet = packetManager.GetPacket();
+                packet?.HandlePacket();
+            }
+        }
+
+
+        /// <summary>
+        ///     Remove a client when it disconnects
+        /// </summary>
+        /// <param name="clientSocket"></param>
+        private static void HandleDisconnect(WebSocket clientSocket)
+        {
+            var connectionId = CookieManager.GetConnectionId(clientSocket);
+            AuthClient temp = null;
+            if (AllClients.TryRemove(connectionId, out temp))
+            {
+                Console.WriteLine("Disconnection from " + clientSocket.RemoteEndpoint);
+                var userCount = AllClients.Count;
+                var extra = userCount < 1 ? "s" : string.Empty;
+                UlteriusTray.ShowMessage($"There are now {userCount} user{extra} connected.", "A user disconnected!");
+            }
+        }
+
+        /// <summary>
+        ///     When a client connects, assign them a unique RSA keypair for handshake.
+        /// </summary>
+        /// <param name="clientSocket"></param>
+        private static async void HandleConnect(WebSocket clientSocket)
+        {
+            var connectionId = CookieManager.GetConnectionId(clientSocket);
+            AuthClient authClient;
+            AllClients.TryGetValue(connectionId, out authClient);
+            var host = new Uri($"ws://{clientSocket.HttpRequest.Headers[RequestHeader.Host]}", UriKind.Absolute);
+
+            if (authClient != null)
+            {
+
+                if (RunningAsService)
+                {
+                    MessageQueueManager agentManager;
+                    if (!authClient.MessageQueueManagers.TryGetValue(22005, out agentManager))
+                    {
+                        if (authClient.MessageQueueManagers.TryAdd(22005,
+                            new MessageQueueManager()))
+                        {
+                            Console.WriteLine("Service Manager Started");
+                        }
+                    }
+                }
+                MessageQueueManager manager;
+                //check if a manager for that port exist, if not, create one
+                
+                if (!authClient.MessageQueueManagers.TryGetValue(host.Port, out manager))
+                {
+                    if (authClient.MessageQueueManagers.TryAdd(host.Port,
+                        new MessageQueueManager()))
+                    {
+                        Console.WriteLine($"Manager started for {host.Port}");
+                    }
+                }
+                return;
+            }
+            Console.WriteLine("Connection from " + clientSocket.RemoteEndpoint);
+            var rsa = new Rsa();
+            rsa.GenerateKeyPairs();
+            var client = new AuthClient
+            {
+                PublicKey = rsa.PublicKey,
+                PrivateKey = rsa.PrivateKey,
+                MessageQueueManagers = new ConcurrentDictionary<int, MessageQueueManager>()
+            };
+          
+            client.MessageQueueManagers.TryAdd(host.Port, new MessageQueueManager());
+            AllClients.AddOrUpdate(connectionId, client, (key, value) => value);
+            await SendWelcomeMessage(client, clientSocket);
+        }
+
+        /// <summary>
+        ///     Sends a new user their unique RSA keypair
+        /// </summary>
+        /// <param name="client"></param>
+        /// <param name="clientSocket"></param>
+        private static async Task SendWelcomeMessage(AuthClient client, WebSocket clientSocket)
+        {
+            var welcomeMessage = JsonConvert.SerializeObject(new
+            {
+                endpoint = "connectedToUlterius",
+                results = new
+                {
+                    message = "Ulterius server online!",
+                    publicKey = Rsa.SecureStringToString(client.PublicKey)
+                }
+            });
+            if (clientSocket != null)
+            {
+                try
+                {
+                    await clientSocket.WriteStringAsync(welcomeMessage, CancellationToken.None);
+                    var userCount = AllClients.Count;
+                    var extra = userCount > 1 ? "s" : string.Empty;
+                    UlteriusTray.ShowMessage($"There are now {userCount} user{extra} connected.", "A new user connected!");
+                }
+                catch (Exception ex)
+                {
+                    Console.WriteLine("Failed to write welcome message " + ex.Message );
+                }
+            }
+        }
+
+        private static void Log(string message)
+        {
+            Console.WriteLine(message);
+        }
+    }
 }
\ No newline at end of file
diff --git a/AgentInterface/Api/Win32/Desktop.cs b/RemoteTaskServer/Api/Win32/Desktop.cs
similarity index 99%
rename from AgentInterface/Api/Win32/Desktop.cs
rename to RemoteTaskServer/Api/Win32/Desktop.cs
index a1a586f..eb01019 100644
--- a/AgentInterface/Api/Win32/Desktop.cs
+++ b/RemoteTaskServer/Api/Win32/Desktop.cs
@@ -7,11 +7,11 @@ using System.Diagnostics;
 using System.Linq;
 using System.Runtime.InteropServices;
 
 #endregion
 
-namespace AgentInterface.Api.Win32
+namespace UlteriusServer.Api.Win32
 {
     /// <summary>
     ///     Encapsulates the Desktop API.
     /// </summary>
     public class Desktop : IDisposable, ICloneable
@@ -59,11 +59,11 @@ namespace AgentInterface.Api.Win32
         private static extern int GetThreadId(IntPtr thread);
 
         [DllImport("kernel32.dll")]
         private static extern int GetProcessId(IntPtr process);
         [DllImport("kernel32.dll")]
-        static extern int GetCurrentThreadId();
+        public static extern int GetCurrentThreadId();
         //
         // Imported winAPI functions.
         //
         [DllImport("user32.dll")]
         private static extern IntPtr CreateDesktop(string lpszDesktop, IntPtr lpszDevice, IntPtr pDevmode, int dwFlags,
diff --git a/RemoteTaskServer/Api/Win32/DesktopWatcher.cs b/RemoteTaskServer/Api/Win32/DesktopWatcher.cs
new file mode 100644
index 0000000..3b856ea
--- /dev/null
+++ b/RemoteTaskServer/Api/Win32/DesktopWatcher.cs
@@ -0,0 +1,61 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace UlteriusServer.Api.Win32
+{
+    public class DesktopWatcher
+    {
+        private static string _lastDesktop;
+        private static Desktop _lastDesktopInput;
+        public static void Start()
+        {
+            var backgroundThread = new Thread(WatchDesktop) { IsBackground = true };
+            backgroundThread.Start();
+            Console.WriteLine($"Desktop Task is running on thread: {Desktop.GetCurrentThreadId()}");
+        }
+
+        private static void WatchDesktop()
+        {
+            while (true)
+            {
+                try
+                {
+                    using (var inputDesktop = new Desktop())
+                    {
+                        inputDesktop.OpenInput();
+                        if (!inputDesktop.DesktopName.Equals(_lastDesktop))
+                        {
+                            if (inputDesktop.Show() && Desktop.SetCurrent(inputDesktop))
+                            {
+                               Console.WriteLine($"Desktop switched from {_lastDesktop} to {inputDesktop.DesktopName} on thread {Desktop.GetCurrentThreadId()}");
+                                _lastDesktop = inputDesktop.DesktopName;
+                                _lastDesktopInput = inputDesktop;
+                                CurrentDesktop = inputDesktop;
+                            }
+                            else
+                            {
+                                var errorMessage = new Win32Exception(Marshal.GetLastWin32Error()).Message;
+                                Console.WriteLine(errorMessage);
+                                _lastDesktopInput?.Close();
+                            }
+                        }
+                    }
+                }
+                catch (Exception ex)
+                {
+                    Console.WriteLine(ex.Message, ex);
+                }
+                Thread.Sleep(1000);
+            }
+        }
+
+        public static string CurrentDesktopName { get; set; }
+
+        public static Desktop CurrentDesktop { get; set; }
+    }
+}
diff --git a/RemoteTaskServer/Api/Win32/Display.cs b/RemoteTaskServer/Api/Win32/Display.cs
new file mode 100644
index 0000000..f3bdc35
--- /dev/null
+++ b/RemoteTaskServer/Api/Win32/Display.cs
@@ -0,0 +1,477 @@
+﻿#region
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Globalization;
+using System.Linq;
+using System.Runtime.InteropServices;
+
+#endregion
+
+namespace UlteriusServer.Api.Win32
+{
+    public class Monitor
+    {
+        public Rectangle Rect { get; set; }
+        public Rectangle WorkRect { get; set; }
+        public bool Primary { get; set; }
+        public string DeviceName { get; set; }
+    }
+
+    public class Display
+    {
+
+       
+        private static IEnumerable<string> GetAllMonitorsFriendlyNames()
+        {
+            uint pathCount, modeCount;
+            var error = GetDisplayConfigBufferSizes(QueryDeviceConfigFlags.QdcOnlyActivePaths, out pathCount,
+                out modeCount);
+            if (error != ErrorSuccess)
+                throw new System.ComponentModel.Win32Exception(error);
+
+            var displayPaths = new DisplayconfigPathInfo[pathCount];
+            var displayModes = new DisplayconfigModeInfo[modeCount];
+            error = QueryDisplayConfig(QueryDeviceConfigFlags.QdcOnlyActivePaths,
+                ref pathCount, displayPaths, ref modeCount, displayModes, IntPtr.Zero);
+            if (error != ErrorSuccess)
+                throw new System.ComponentModel.Win32Exception(error);
+
+            for (var i = 0; i < modeCount; i++)
+                if (displayModes[i].infoType == DisplayconfigModeInfoType.DisplayconfigModeInfoTypeTarget)
+                    yield return MonitorFriendlyName(displayModes[i].adapterId, displayModes[i].id);
+        }
+
+        public static string GetDeviceFriendlyName(int screenIndex)
+        {
+            var allFriendlyNames = GetAllMonitorsFriendlyNames().ToList();
+            if (screenIndex > allFriendlyNames.Count)
+            {
+                return null;
+            }
+            return allFriendlyNames.ElementAtOrDefault(screenIndex) ?? "Unknown";
+        }
+
+        private static string MonitorFriendlyName(Luid adapterId, uint targetId)
+        {
+            var deviceName = new DisplayconfigTargetDeviceName
+            {
+                header =
+                {
+                    size = (uint) Marshal.SizeOf(typeof(DisplayconfigTargetDeviceName)),
+                    adapterId = adapterId,
+                    id = targetId,
+                    type = DisplayconfigDeviceInfoType.DisplayconfigDeviceInfoGetTargetName
+                }
+            };
+            var error = DisplayConfigGetDeviceInfo(ref deviceName);
+            if (error != ErrorSuccess)
+                throw new System.ComponentModel.Win32Exception(error);
+            return deviceName.monitorFriendlyDeviceName;
+        }
+
+        public const int ErrorSuccess = 0;
+        [DllImport("user32.dll")]
+        public static extern int GetDisplayConfigBufferSizes(
+            QueryDeviceConfigFlags flags, out uint numPathArrayElements, out uint numModeInfoArrayElements);
+
+        [DllImport("user32.dll")]
+        public static extern int QueryDisplayConfig(
+            QueryDeviceConfigFlags flags,
+            ref uint numPathArrayElements, [Out] DisplayconfigPathInfo[] pathInfoArray,
+            ref uint numModeInfoArrayElements, [Out] DisplayconfigModeInfo[] modeInfoArray,
+            IntPtr currentTopologyId
+        );
+        [StructLayout(LayoutKind.Sequential)]
+        public struct DisplayconfigTargetDeviceNameFlags
+        {
+            public uint value;
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        public struct DisplayconfigDeviceInfoHeader
+        {
+            public DisplayconfigDeviceInfoType type;
+            public uint size;
+            public Luid adapterId;
+            public uint id;
+        }
+
+        public enum DisplayconfigDeviceInfoType : uint
+        {
+            DisplayconfigDeviceInfoGetSourceName = 1,
+            DisplayconfigDeviceInfoGetTargetName = 2,
+            DisplayconfigDeviceInfoGetTargetPreferredMode = 3,
+            DisplayconfigDeviceInfoGetAdapterName = 4,
+            DisplayconfigDeviceInfoSetTargetPersistence = 5,
+            DisplayconfigDeviceInfoGetTargetBaseType = 6,
+            DisplayconfigDeviceInfoForceUint32 = 0xFFFFFFFF
+        }
+        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+        public struct DisplayconfigTargetDeviceName
+        {
+            public DisplayconfigDeviceInfoHeader header;
+            public DisplayconfigTargetDeviceNameFlags flags;
+            public DisplayconfigVideoOutputTechnology outputTechnology;
+            public ushort edidManufactureId;
+            public ushort edidProductCodeId;
+            public uint connectorInstance;
+
+            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string monitorFriendlyDeviceName;
+
+            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string monitorDevicePath;
+        }
+        [StructLayout(LayoutKind.Sequential)]
+        public struct DisplayconfigModeInfo
+        {
+            public DisplayconfigModeInfoType infoType;
+            public uint id;
+            public Luid adapterId;
+            public DisplayconfigModeInfoUnion modeInfo;
+        }
+        [DllImport("user32.dll")]
+        public static extern int DisplayConfigGetDeviceInfo(ref DisplayconfigTargetDeviceName deviceName);
+
+        public enum QueryDeviceConfigFlags : uint
+        {
+            QdcAllPaths = 0x00000001,
+            QdcOnlyActivePaths = 0x00000002,
+            QdcDatabaseCurrent = 0x00000004
+        }
+        public enum DisplayconfigModeInfoType : uint
+        {
+            DisplayconfigModeInfoTypeSource = 1,
+            DisplayconfigModeInfoTypeTarget = 2,
+            DisplayconfigModeInfoTypeForceUint32 = 0xFFFFFFFF
+        }
+        [StructLayout(LayoutKind.Explicit)]
+        public struct DisplayconfigModeInfoUnion
+        {
+            [FieldOffset(0)] public DisplayconfigTargetMode targetMode;
+
+            [FieldOffset(0)] public DisplayconfigSourceMode sourceMode;
+        }
+        [StructLayout(LayoutKind.Sequential)]
+        public struct DisplayconfigTargetMode
+        {
+            public DisplayconfigVideoSignalInfo targetVideoSignalInfo;
+        }
+        [StructLayout(LayoutKind.Sequential)]
+        public struct DisplayconfigPathInfo
+        {
+            public DisplayconfigPathSourceInfo sourceInfo;
+            public DisplayconfigPathTargetInfo targetInfo;
+            public uint flags;
+        }
+        [StructLayout(LayoutKind.Sequential)]
+        public struct DisplayconfigSourceMode
+        {
+            public uint width;
+            public uint height;
+            public DisplayconfigPixelformat pixelFormat;
+            public Pointl position;
+        }
+        [StructLayout(LayoutKind.Sequential)]
+        public struct DisplayconfigPathSourceInfo
+        {
+            public Luid adapterId;
+            public uint id;
+            public uint modeInfoIdx;
+            public uint statusFlags;
+        }
+
+        public static Rectangle GetWindowRectangle()
+        {
+            var scBounds = new RECT();
+            GetWindowRect(GetDesktopWindow(), ref scBounds);
+            return scBounds;
+        }
+
+        [DllImport("user32.dll", SetLastError = true)]
+        [return: MarshalAs(UnmanagedType.Bool)]
+        public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
+
+
+
+        [DllImport("user32.dll", EntryPoint = "GetDesktopWindow")]
+        public static extern IntPtr GetDesktopWindow();
+
+
+        [StructLayout(LayoutKind.Sequential)]
+        public struct RECT
+        {
+            public int Left, Top, Right, Bottom;
+
+            public RECT(int left, int top, int right, int bottom)
+            {
+                Left = left;
+                Top = top;
+                Right = right;
+                Bottom = bottom;
+            }
+
+            public RECT(Rectangle r) : this(r.Left, r.Top, r.Right, r.Bottom)
+            {
+            }
+
+            public int X
+            {
+                get => Left;
+                set
+                {
+                    Right -= Left - value;
+                    Left = value;
+                }
+            }
+
+            public int Y
+            {
+                get => Top;
+                set
+                {
+                    Bottom -= Top - value;
+                    Top = value;
+                }
+            }
+
+            public int Height
+            {
+                get => Bottom - Top;
+                set => Bottom = value + Top;
+            }
+
+            public int Width
+            {
+                get => Right - Left;
+                set => Right = value + Left;
+            }
+
+
+            public Size Size
+            {
+                get => new Size(Width, Height);
+                set
+                {
+                    Width = value.Width;
+                    Height = value.Height;
+                }
+            }
+
+            public static implicit operator Rectangle(RECT r)
+            {
+                return new Rectangle(r.Left, r.Top, r.Width, r.Height);
+            }
+
+            public static implicit operator RECT(Rectangle r)
+            {
+                return new RECT(r);
+            }
+
+            public static bool operator ==(RECT r1, RECT r2)
+            {
+                return r1.Equals(r2);
+            }
+
+            public static bool operator !=(RECT r1, RECT r2)
+            {
+                return !r1.Equals(r2);
+            }
+
+            public bool Equals(RECT r)
+            {
+                return r.Left == Left && r.Top == Top && r.Right == Right && r.Bottom == Bottom;
+            }
+
+            public override bool Equals(object obj)
+            {
+                if (obj is RECT)
+                    return Equals((RECT)obj);
+                if (obj is Rectangle)
+                    return Equals(new RECT((Rectangle)obj));
+                return false;
+            }
+
+            public override int GetHashCode()
+            {
+                return ((Rectangle)this).GetHashCode();
+            }
+
+            public override string ToString()
+            {
+                return string.Format(CultureInfo.CurrentCulture, "{{Left={0},Top={1},Right={2},Bottom={3}}}", Left, Top,
+                    Right, Bottom);
+            }
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        public struct Displayconfig2Dregion
+        {
+            public uint cx;
+            public uint cy;
+        }
+        [StructLayout(LayoutKind.Sequential)]
+        public struct Pointl
+        {
+            private readonly int x;
+            private readonly int y;
+        }
+        public enum DisplayconfigPixelformat : uint
+        {
+            DisplayconfigPixelformat8Bpp = 1,
+            DisplayconfigPixelformat16Bpp = 2,
+            DisplayconfigPixelformat24Bpp = 3,
+            DisplayconfigPixelformat32Bpp = 4,
+            DisplayconfigPixelformatNongdi = 5,
+            DisplayconfigPixelformatForceUint32 = 0xffffffff
+        }
+        public struct DisplayconfigVideoSignalInfo
+        {
+            public ulong pixelRate;
+            public DisplayconfigRational hSyncFreq;
+            public DisplayconfigRational vSyncFreq;
+            public Displayconfig2Dregion activeSize;
+            public Displayconfig2Dregion totalSize;
+            public uint videoStandard;
+            public DisplayconfigScanlineOrdering scanLineOrdering;
+        }
+        [StructLayout(LayoutKind.Sequential)]
+        public struct DisplayconfigPathTargetInfo
+        {
+            public Luid adapterId;
+            public uint id;
+            public uint modeInfoIdx;
+            private readonly DisplayconfigVideoOutputTechnology outputTechnology;
+            private readonly DisplayconfigRotation rotation;
+            private readonly DisplayconfigScaling scaling;
+            private readonly DisplayconfigRational refreshRate;
+            private readonly DisplayconfigScanlineOrdering scanLineOrdering;
+            public bool targetAvailable;
+            public uint statusFlags;
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        public struct Luid
+        {
+            public uint LowPart;
+            public int HighPart;
+        }
+
+
+        public enum DisplayconfigScanlineOrdering : uint
+        {
+            DisplayconfigScanlineOrderingUnspecified = 0,
+            DisplayconfigScanlineOrderingProgressive = 1,
+            DisplayconfigScanlineOrderingInterlaced = 2,
+            DisplayconfigScanlineOrderingInterlacedUpperfieldfirst = DisplayconfigScanlineOrderingInterlaced,
+            DisplayconfigScanlineOrderingInterlacedLowerfieldfirst = 3,
+            DisplayconfigScanlineOrderingForceUint32 = 0xFFFFFFFF
+        }
+
+        public enum DisplayconfigVideoOutputTechnology : uint
+        {
+            DisplayconfigOutputTechnologyOther = 0xFFFFFFFF,
+            DisplayconfigOutputTechnologyHd15 = 0,
+            DisplayconfigOutputTechnologySvideo = 1,
+            DisplayconfigOutputTechnologyCompositeVideo = 2,
+            DisplayconfigOutputTechnologyComponentVideo = 3,
+            DisplayconfigOutputTechnologyDvi = 4,
+            DisplayconfigOutputTechnologyHdmi = 5,
+            DisplayconfigOutputTechnologyLvds = 6,
+            DisplayconfigOutputTechnologyDJpn = 8,
+            DisplayconfigOutputTechnologySdi = 9,
+            DisplayconfigOutputTechnologyDisplayportExternal = 10,
+            DisplayconfigOutputTechnologyDisplayportEmbedded = 11,
+            DisplayconfigOutputTechnologyUdiExternal = 12,
+            DisplayconfigOutputTechnologyUdiEmbedded = 13,
+            DisplayconfigOutputTechnologySdtvdongle = 14,
+            DisplayconfigOutputTechnologyMiracast = 15,
+            DisplayconfigOutputTechnologyInternal = 0x80000000,
+            DisplayconfigOutputTechnologyForceUint32 = 0xFFFFFFFF
+        }
+        [StructLayout(LayoutKind.Sequential)]
+        public struct DisplayconfigRational
+        {
+            public uint Numerator;
+            public uint Denominator;
+        }
+
+        public enum DisplayconfigRotation : uint
+        {
+            DisplayconfigRotationIdentity = 1,
+            DisplayconfigRotationRotate90 = 2,
+            DisplayconfigRotationRotate180 = 3,
+            DisplayconfigRotationRotate270 = 4,
+            DisplayconfigRotationForceUint32 = 0xFFFFFFFF
+        }
+
+        public enum DisplayconfigScaling : uint
+        {
+            DisplayconfigScalingIdentity = 1,
+            DisplayconfigScalingCentered = 2,
+            DisplayconfigScalingStretched = 3,
+            DisplayconfigScalingAspectratiocenteredmax = 4,
+            DisplayconfigScalingCustom = 5,
+            DisplayconfigScalingPreferred = 128,
+            DisplayconfigScalingForceUint32 = 0xFFFFFFFF
+        }
+        public const int MONITORINFOF_PRIMARY = 0x1;
+        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+        public struct MONITORINFOEX
+        {
+            public int cbSize;
+            public RECT rcMonitor;
+            public RECT rcWork;
+            public int dwFlags;
+            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
+            public string szDevice;
+        }
+        public delegate bool MonitorEnumProc(IntPtr hMonitor, IntPtr hdcMonitor, ref RECT lprcMonitor, IntPtr dwData);
+        [DllImport("User32.dll", CharSet = CharSet.Unicode)]
+        public static extern bool GetMonitorInfo(IntPtr hMonitor, ref MONITORINFOEX lpmi);
+
+        [DllImport("User32.dll", CharSet = CharSet.Unicode)]
+        public static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, MonitorEnumProc lpfnEnum, IntPtr dwData);
+
+        private static List<Monitor> GetMonitors()
+        {
+            List<Monitor> monitors = new List<Monitor>();
+
+            EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero,
+                (IntPtr hMonitor, IntPtr hdcMonitor, ref RECT lprcMonitor, IntPtr dwData) =>
+                {
+                    MONITORINFOEX monitorInfo = new MONITORINFOEX();
+                    monitorInfo.cbSize = Marshal.SizeOf(typeof(MONITORINFOEX));
+
+                    GetMonitorInfo(hMonitor, ref monitorInfo);
+
+                    monitors.Add(new Monitor()
+                    {
+                        Primary = (monitorInfo.dwFlags & MONITORINFOF_PRIMARY) != 0,
+                        DeviceName = monitorInfo.szDevice,
+                        Rect = Rectangle.FromLTRB(monitorInfo.rcMonitor.Left,
+                            monitorInfo.rcMonitor.Top,
+                            monitorInfo.rcMonitor.Right,
+                            monitorInfo.rcMonitor.Bottom),
+                        WorkRect = Rectangle.FromLTRB(monitorInfo.rcWork.Left,
+                            monitorInfo.rcWork.Top,
+                            monitorInfo.rcWork.Right,
+                            monitorInfo.rcWork.Bottom)
+                    });
+
+                    return true;
+                },
+                IntPtr.Zero
+            );
+
+            return monitors;
+        }
+        public static int X { get; set; }
+
+        public static int Y { get; set; }
+
+        public static int Height { get; set; }
+
+        public static int Width { get; set; }
+    }
+}
\ No newline at end of file
diff --git a/AgentInterface/Api/ScreenShare/DesktopDuplication/DesktopDuplicationException.cs b/RemoteTaskServer/Api/Win32/ScreenShare/DesktopDuplication/DesktopDuplicationException.cs
similarity index 73%
rename from AgentInterface/Api/ScreenShare/DesktopDuplication/DesktopDuplicationException.cs
rename to RemoteTaskServer/Api/Win32/ScreenShare/DesktopDuplication/DesktopDuplicationException.cs
index ceedd64..9c5e800 100644
--- a/AgentInterface/Api/ScreenShare/DesktopDuplication/DesktopDuplicationException.cs
+++ b/RemoteTaskServer/Api/Win32/ScreenShare/DesktopDuplication/DesktopDuplicationException.cs
@@ -1,8 +1,8 @@
 ﻿using System;
 
-namespace AgentInterface.Api.ScreenShare.DesktopDuplication
+namespace UlteriusServer.Api.Win32.ScreenShare.DesktopDuplication
 {
     public class DesktopDuplicationException : Exception
     {
         public DesktopDuplicationException(string message)
             : base(message) { }
diff --git a/AgentInterface/Api/ScreenShare/DesktopDuplication/DesktopDuplicator.cs b/RemoteTaskServer/Api/Win32/ScreenShare/DesktopDuplication/DesktopDuplicator.cs
similarity index 83%
rename from AgentInterface/Api/ScreenShare/DesktopDuplication/DesktopDuplicator.cs
rename to RemoteTaskServer/Api/Win32/ScreenShare/DesktopDuplication/DesktopDuplicator.cs
index d92c739..24d2281 100644
--- a/AgentInterface/Api/ScreenShare/DesktopDuplication/DesktopDuplicator.cs
+++ b/RemoteTaskServer/Api/Win32/ScreenShare/DesktopDuplication/DesktopDuplicator.cs
@@ -1,354 +1,355 @@
-﻿#region
-
-using System;
-using System.Drawing;
-using System.Drawing.Imaging;
-using System.Runtime.InteropServices;
-using SharpDX;
-using SharpDX.Direct3D;
-using SharpDX.Direct3D11;
-using SharpDX.DXGI;
-using SharpDX.Mathematics.Interop;
-using Device = SharpDX.Direct3D11.Device;
-using MapFlags = SharpDX.Direct3D11.MapFlags;
-using Point = System.Drawing.Point;
-using Rectangle = SharpDX.Rectangle;
-using Resource = SharpDX.DXGI.Resource;
-using ResultCode = SharpDX.DXGI.ResultCode;
-
-#endregion
-
-namespace AgentInterface.Api.ScreenShare.DesktopDuplication
-{
-    /// <summary>
-    ///     Provides access to frame-by-frame updates of a particular desktop (i.e. one monitor), with image and cursor
-    ///     information.
-    /// </summary>
-    public class DesktopDuplicator
-    {
-        private readonly OutputDuplication _mDeskDupl;
-        private readonly Device _mDevice;
-        private readonly Texture2DDescription _mTextureDesc;
-        private readonly int _mWhichOutputDevice;
-        private Texture2D _desktopImageTexture;
-
-        private Bitmap _finalImage1, _finalImage2;
-        private OutputDuplicateFrameInformation _frameInfo;
-        private bool _isFinalImage1;
-        private OutputDescription _mOutputDesc;
-
-      
-        /// <summary>
-        ///     Duplicates the output of the specified monitor on the specified graphics adapter.
-        /// </summary>
-        /// <param name="whichGraphicsCardAdapter">The adapter which contains the desired outputs.</param>
-        /// <param name="whichOutputDevice">
-        ///     The output device to duplicate (i.e. monitor). Begins with zero, which seems to
-        ///     correspond to the primary monitor.
-        /// </param>
-        public DesktopDuplicator()
-        {
-
-
-            Adapter1 adapter;
-            try
-            {
-                adapter = GetBestAdapter(out int bestAdapaterIndex);
-                if (adapter == null) throw new SharpDXException();
-                Console.WriteLine($"Using the {adapter.Description.Description} for screen share.");
-            }
-            catch (SharpDXException)
-            {
-                ScreenData.CanUseGpuAcceleration = false;
-                throw new DesktopDuplicationException("Could not find the specified graphics card adapter.");
-            }
-            DeviceCreationFlags flags = DeviceCreationFlags.BgraSupport;
-            _mDevice = new Device(adapter, flags, FeatureLevel.Level_11_0);
-            Output output;
-            try
-            {
-                output = adapter.GetOutput(0);
-            }
-            catch (SharpDXException)
-            {
-                ScreenData.CanUseGpuAcceleration = false;
-                throw new DesktopDuplicationException("Could not find the specified output device.");
-            }
-            var output1 = output.QueryInterface<Output1>();
-            _mOutputDesc = output.Description;
-            _mTextureDesc = new Texture2DDescription
-            {
-                CpuAccessFlags = CpuAccessFlags.Read,
-                BindFlags = BindFlags.None,
-                Format = Format.B8G8R8A8_UNorm,
-                Width = ((Rectangle) _mOutputDesc.DesktopBounds).Width,
-                Height = ((Rectangle) _mOutputDesc.DesktopBounds).Height,
-                OptionFlags = ResourceOptionFlags.None,
-                MipLevels = 1,
-                ArraySize = 1,
-                SampleDescription = {Count = 1, Quality = 0},
-                Usage = ResourceUsage.Staging
-            };
-
-            try
-            {
-                _mDeskDupl = output1.DuplicateOutput(_mDevice);
-            }
-            catch (SharpDXException ex)
-            {
-                if (ex.ResultCode.Code == ResultCode.NotCurrentlyAvailable.Result.Code)
-                    throw new DesktopDuplicationException(
-                        "There is already the maximum number of applications using the Desktop Duplication API running, please close one of the applications and try again.");
-            }
-        }
-
-        private Bitmap FinalImage
-        {
-            get { return _isFinalImage1 ? _finalImage1 : _finalImage2; }
-            set
-            {
-                if (_isFinalImage1)
-                {
-                    _finalImage2 = value;
-                    _finalImage1?.Dispose();
-                }
-                else
-                {
-                    _finalImage1 = value;
-                    _finalImage2?.Dispose();
-                }
-                _isFinalImage1 = !_isFinalImage1;
-            }
-        }
-
-        /// <summary>
-        ///     Finds the most capable graphics card.
-        /// </summary>
-        /// <returns></returns>
-        private static Adapter1 GetBestAdapter(out int bestAdapterIndex)
-        {
-            using (var dxgiFactory = new Factory1())
-            {
-                Adapter1 bestAdapter = null;
-                bestAdapterIndex = -1;
-                var adapterIndex = -1;
-                long bestVideoMemory = 0;
-                long bestSystemMemory = 0;
-
-                foreach (var dxgiAdapter in dxgiFactory.Adapters1)
-                {
-                    adapterIndex++;
-
-                    // not skip the render only WARP device
-                    if (dxgiAdapter.Description.VendorId != 0x1414 || dxgiAdapter.Description.DeviceId != 0x8c)
-                        if (dxgiAdapter.Outputs == null || dxgiAdapter.Outputs.Length == 0)
-                            continue;
-
-                    var level = Device.GetSupportedFeatureLevel(dxgiAdapter);
-
-                    if (level < FeatureLevel.Level_11_0)
-                        continue;
-                    long videoMemory = (uint) dxgiAdapter.Description.DedicatedVideoMemory;
-                    long systemMemory = (uint) dxgiAdapter.Description.DedicatedSystemMemory;
-
-                    if (bestAdapter != null && videoMemory <= bestVideoMemory &&
-                        (videoMemory != bestVideoMemory || systemMemory <= bestSystemMemory)) continue;
-                    bestAdapter = dxgiAdapter;
-                    bestAdapterIndex = adapterIndex;
-                    bestVideoMemory = videoMemory;
-                    bestSystemMemory = systemMemory;
-                }
-
-                return bestAdapter;
-            }
-        }
-
-        /// <summary>
-        ///     Retrieves the latest desktop image and associated metadata.
-        /// </summary>
-        public DesktopFrame GetLatestFrame()
-        {
-            var frame = new DesktopFrame();
-            // Try to get the latest frame; this may timeout
-            var retrievalTimedOut = RetrieveFrame();
-            if (retrievalTimedOut)
-                return null;
-            try
-            {
-                RetrieveFrameMetadata(frame);
-                //we don't need cursor info
-                //RetrieveCursorMetadata(frame);
-                //we dont need a full frame
-                //ProcessFrame(frame);
-            }
-            catch
-            {
-                ReleaseFrame();
-            }
-            try
-            {
-                ReleaseFrame();
-            }
-            catch
-            {
-                //    throw new DesktopDuplicationException("Couldn't release frame.");  
-            }
-            return frame;
-        }
-
-        private bool RetrieveFrame()
-        {
-            if (_desktopImageTexture == null)
-                _desktopImageTexture = new Texture2D(_mDevice, _mTextureDesc);
-            Resource desktopResource = null;
-            _frameInfo = new OutputDuplicateFrameInformation();
-            try
-            {
-                _mDeskDupl.AcquireNextFrame(500, out _frameInfo, out desktopResource);
-            }
-            catch (SharpDXException ex)
-            {
-                if (ex.ResultCode.Code == ResultCode.WaitTimeout.Result.Code)
-                    return true;
-                if (ex.ResultCode.Failure)
-                {
-                    //return true;
-                    desktopResource?.Dispose();
-                    throw new DesktopDuplicationException("Failed to acquire next frame.");
-                }
-            }
-            using (var tempTexture = desktopResource?.QueryInterface<Texture2D>())
-            {
-                _mDevice.ImmediateContext.CopyResource(tempTexture, _desktopImageTexture);
-            }
-            desktopResource?.Dispose();
-            return false;
-        }
-
-        private void RetrieveFrameMetadata(DesktopFrame frame)
-        {
-            if (_frameInfo.TotalMetadataBufferSize > 0)
-            {
-                // Get moved regions
-                var movedRegionsLength = 0;
-                var movedRectangles = new OutputDuplicateMoveRectangle[_frameInfo.TotalMetadataBufferSize];
-                _mDeskDupl.GetFrameMoveRects(movedRectangles.Length, movedRectangles, out movedRegionsLength);
-                frame.MovedRegions =
-                    new MovedRegion[movedRegionsLength / Marshal.SizeOf(typeof(OutputDuplicateMoveRectangle))];
-                for (var i = 0; i < frame.MovedRegions.Length; i++)
-                {
-                    var destRect = (Rectangle) movedRectangles[i].DestinationRect;
-                    frame.MovedRegions[i] = new MovedRegion
-                    {
-                        Source = new Point(movedRectangles[i].SourcePoint.X, movedRectangles[i].SourcePoint.Y),
-                        Destination =
-                            new global::System.Drawing.Rectangle(destRect.X, destRect.Y, destRect.Width, destRect.Height)
-                    };
-                }
-
-                // Get dirty regions
-                var dirtyRegionsLength = 0;
-                var dirtyRectangles = new RawRectangle[_frameInfo.TotalMetadataBufferSize];
-                _mDeskDupl.GetFrameDirtyRects(dirtyRectangles.Length, dirtyRectangles, out dirtyRegionsLength);
-                frame.UpdatedRegions =
-                    new global::System.Drawing.Rectangle[dirtyRegionsLength / Marshal.SizeOf(typeof(Rectangle))];
-                frame.FinishedRegions = new FinishedRegions[frame.UpdatedRegions.Length];
-                for (var i = 0; i < frame.UpdatedRegions.Length; i++)
-                {
-                    var dirtyRect = (Rectangle) dirtyRectangles[i];
-                    var rect = new global::System.Drawing.Rectangle(dirtyRect.X, dirtyRect.Y, dirtyRect.Width,
-                        dirtyRect.Height);
-
-
-                    frame.FinishedRegions[i] = new FinishedRegions
-                    {
-                        Destination = rect,
-                        Frame = ExtractRect(rect.X, rect.Y, rect.Width, rect.Height)
-                    };
-                }
-            }
-            else
-            {
-                frame.MovedRegions = new MovedRegion[0];
-                frame.UpdatedRegions = new global::System.Drawing.Rectangle[0];
-            }
-        }
-
-
-        private Bitmap ExtractRect(int originX, int originY, int width, int height)
-        {
-            // Get the desktop capture screenTexture
-            var mapSource = _mDevice.ImmediateContext.MapSubresource(_desktopImageTexture, 0, MapMode.Read,
-                MapFlags.None);
-
-            // Create Drawing.Bitmap
-
-            var bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); //不能是ARGB
-            var boundsRect = new global::System.Drawing.Rectangle(0, 0, width, height);
-
-            // Copy pixels from screen capture Texture to GDI bitmap
-            var mapDest = bitmap.LockBits(boundsRect, ImageLockMode.WriteOnly, bitmap.PixelFormat);
-            var sourcePtr = mapSource.DataPointer;
-            var destPtr = mapDest.Scan0;
-
-            sourcePtr = IntPtr.Add(sourcePtr, originY * mapSource.RowPitch + originX * 4);
-            for (var y = 0; y < height; y++)
-            {
-                // Copy a single line 
-
-                Utilities.CopyMemory(destPtr, sourcePtr, width * 4);
-
-                // Advance pointers
-                if (y != height - 1)
-                    sourcePtr = IntPtr.Add(sourcePtr, mapSource.RowPitch);
-                destPtr = IntPtr.Add(destPtr, mapDest.Stride);
-            }
-
-            // Release source and dest locks
-            bitmap.UnlockBits(mapDest);
-            _mDevice.ImmediateContext.UnmapSubresource(_desktopImageTexture, 0);
-            return bitmap;
-        }
-
-        private void ProcessFrame(DesktopFrame frame)
-        {
-            // Get the desktop capture texture
-            var mapSource = _mDevice.ImmediateContext.MapSubresource(_desktopImageTexture, 0, MapMode.Read,
-                MapFlags.None);
-            var bounds = (Rectangle) _mOutputDesc.DesktopBounds;
-            FinalImage = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format32bppArgb);
-            var boundsRect = new global::System.Drawing.Rectangle(0, 0, bounds.Width, bounds.Height);
-            // Copy pixels from screen capture Texture to GDI bitmap
-            var mapDest = FinalImage.LockBits(boundsRect, ImageLockMode.WriteOnly, FinalImage.PixelFormat);
-            var sourcePtr = mapSource.DataPointer;
-            var destPtr = mapDest.Scan0;
-            for (var y = 0; y < bounds.Height; y++)
-            {
-                // Copy a single line 
-                Utilities.CopyMemory(destPtr, sourcePtr, bounds.Width * 4);
-
-                // Advance pointers
-                sourcePtr = IntPtr.Add(sourcePtr, mapSource.RowPitch);
-                destPtr = IntPtr.Add(destPtr, mapDest.Stride);
-            }
-
-            // Release source and dest locks
-            FinalImage.UnlockBits(mapDest);
-            _mDevice.ImmediateContext.UnmapSubresource(_desktopImageTexture, 0);
-            frame.DesktopImage = (Bitmap) FinalImage.Clone();
-        }
-
-        private void ReleaseFrame()
-        {
-            try
-            {
-                _mDeskDupl.ReleaseFrame();
-            }
-            catch (SharpDXException ex)
-            {
-                if (ex.ResultCode.Failure)
-                    throw new DesktopDuplicationException("Failed to release frame.");
-            }
-        }
-    }
+﻿#region
+
+using System;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Runtime.InteropServices;
+using SharpDX;
+using SharpDX.Direct3D;
+using SharpDX.Direct3D11;
+using SharpDX.DXGI;
+using SharpDX.Mathematics.Interop;
+using Device = SharpDX.Direct3D11.Device;
+using MapFlags = SharpDX.Direct3D11.MapFlags;
+using Point = System.Drawing.Point;
+using Rectangle = SharpDX.Rectangle;
+using Resource = SharpDX.DXGI.Resource;
+using ResultCode = SharpDX.DXGI.ResultCode;
+
+#endregion
+
+namespace UlteriusServer.Api.Win32.ScreenShare.DesktopDuplication
+{
+    /// <summary>
+    ///     Provides access to frame-by-frame updates of a particular desktop (i.e. one monitor), with image and cursor
+    ///     information.
+    /// </summary>
+    public class DesktopDuplicator
+    {
+        private readonly OutputDuplication _mDeskDupl;
+        private readonly Device _mDevice;
+        private readonly Texture2DDescription _mTextureDesc;
+        private readonly int _mWhichOutputDevice;
+        private Texture2D _desktopImageTexture;
+
+        private Bitmap _finalImage1, _finalImage2;
+        private OutputDuplicateFrameInformation _frameInfo;
+        private bool _isFinalImage1;
+        private OutputDescription _mOutputDesc;
+
+        /// <summary>
+        /// Duplicates the output of the specified monitor.
+        /// </summary>
+        /// <param name="whichMonitor">The output device to duplicate (i.e. monitor). Begins with zero, which seems to correspond to the primary monitor.</param>
+        public DesktopDuplicator(int whichMonitor)
+            : this(0, whichMonitor) { }
+
+        /// <summary>
+        ///     Duplicates the output of the specified monitor on the specified graphics adapter.
+        /// </summary>
+        /// <param name="whichGraphicsCardAdapter">The adapter which contains the desired outputs.</param>
+        /// <param name="whichOutputDevice">
+        ///     The output device to duplicate (i.e. monitor). Begins with zero, which seems to
+        ///     correspond to the primary monitor.
+        /// </param>
+        public DesktopDuplicator(int whichGraphicsCardAdapter, int whichOutputDevice)
+        {
+            _mWhichOutputDevice = whichOutputDevice;
+            Adapter1 adapter;
+            try
+            {
+                adapter = new Factory1().GetAdapter1(whichGraphicsCardAdapter);
+            }
+            catch (SharpDXException)
+            {
+                throw new DesktopDuplicationException("Could not find the specified graphics card adapter.");
+            }
+           _mDevice = new Device(adapter);
+            Output output = null;
+            try
+            {
+                output = adapter.GetOutput(whichOutputDevice);
+            }
+            catch (SharpDXException)
+            {
+                throw new DesktopDuplicationException("Could not find the specified output device.");
+            }
+            var output1 = output.QueryInterface<Output1>();
+            _mOutputDesc = output.Description;
+            _mTextureDesc = new Texture2DDescription()
+            {
+                CpuAccessFlags = CpuAccessFlags.Read,
+                BindFlags = BindFlags.None,
+                Format = Format.B8G8R8A8_UNorm,
+                Width = ((Rectangle)_mOutputDesc.DesktopBounds).Width,
+                Height = ((Rectangle)_mOutputDesc.DesktopBounds).Height,
+                OptionFlags = ResourceOptionFlags.None,
+                MipLevels = 1,
+                ArraySize = 1,
+                SampleDescription = { Count = 1, Quality = 0 },
+                Usage = ResourceUsage.Staging
+            };
+
+            try
+            {
+                _mDeskDupl = output1.DuplicateOutput(_mDevice);
+            }
+            catch (SharpDXException ex)
+            {
+                if (ex.ResultCode.Code == ResultCode.NotCurrentlyAvailable.Result.Code)
+                {
+                    throw new DesktopDuplicationException("There is already the maximum number of applications using the Desktop Duplication API running, please close one of the applications and try again.");
+                }
+            }
+        }
+
+        private Bitmap FinalImage
+        {
+            get => _isFinalImage1 ? _finalImage1 : _finalImage2;
+            set
+            {
+                if (_isFinalImage1)
+                {
+                    _finalImage2 = value;
+                    _finalImage1?.Dispose();
+                }
+                else
+                {
+                    _finalImage1 = value;
+                    _finalImage2?.Dispose();
+                }
+                _isFinalImage1 = !_isFinalImage1;
+            }
+        }
+
+        /// <summary>
+        ///     Finds the most capable graphics card.
+        /// </summary>
+        /// <returns></returns>
+        private static Adapter1 GetBestAdapter(out int bestAdapterIndex)
+        {
+            using (var dxgiFactory = new Factory1())
+            {
+                Adapter1 bestAdapter = null;
+                bestAdapterIndex = -1;
+                var adapterIndex = -1;
+                long bestVideoMemory = 0;
+                long bestSystemMemory = 0;
+
+                foreach (var dxgiAdapter in dxgiFactory.Adapters1)
+                {
+                    adapterIndex++;
+
+                    // not skip the render only WARP device
+                    if (dxgiAdapter.Description.VendorId != 0x1414 || dxgiAdapter.Description.DeviceId != 0x8c)
+                        if (dxgiAdapter.Outputs == null || dxgiAdapter.Outputs.Length == 0)
+                            continue;
+
+                    var level = Device.GetSupportedFeatureLevel(dxgiAdapter);
+
+                    if (level < FeatureLevel.Level_11_0)
+                        continue;
+                    long videoMemory = (uint) dxgiAdapter.Description.DedicatedVideoMemory;
+                    long systemMemory = (uint) dxgiAdapter.Description.DedicatedSystemMemory;
+
+                    if (bestAdapter != null && videoMemory <= bestVideoMemory &&
+                        (videoMemory != bestVideoMemory || systemMemory <= bestSystemMemory)) continue;
+                    bestAdapter = dxgiAdapter;
+                    bestAdapterIndex = adapterIndex;
+                    bestVideoMemory = videoMemory;
+                    bestSystemMemory = systemMemory;
+                }
+
+                return bestAdapter;
+            }
+        }
+
+        /// <summary>
+        ///     Retrieves the latest desktop image and associated metadata.
+        /// </summary>
+        public DesktopFrame GetLatestFrame()
+        {
+            var frame = new DesktopFrame();
+            // Try to get the latest frame; this may timeout
+            var retrievalTimedOut = RetrieveFrame();
+            if (retrievalTimedOut)
+                return null;
+            try
+            {
+                RetrieveFrameMetadata(frame);
+                //we don't need cursor info
+                //RetrieveCursorMetadata(frame);
+                //we dont need a full frame
+                //ProcessFrame(frame);
+            }
+            catch
+            {
+                ReleaseFrame();
+            }
+            try
+            {
+                ReleaseFrame();
+            }
+            catch
+            {
+                //    throw new DesktopDuplicationException("Couldn't release frame.");  
+            }
+            return frame;
+        }
+
+        private bool RetrieveFrame()
+        {
+            if (_desktopImageTexture == null)
+                _desktopImageTexture = new Texture2D(_mDevice, _mTextureDesc);
+            Resource desktopResource = null;
+            _frameInfo = new OutputDuplicateFrameInformation();
+            try
+            {
+                _mDeskDupl.AcquireNextFrame(500, out _frameInfo, out desktopResource);
+            }
+            catch (SharpDXException ex)
+            {
+                if (ex.ResultCode.Code == ResultCode.WaitTimeout.Result.Code)
+                    return true;
+                if (ex.ResultCode.Failure)
+                {
+                    //return true;
+                    desktopResource?.Dispose();
+                    throw new DesktopDuplicationException("Failed to acquire next frame.");
+                }
+            }
+            using (var tempTexture = desktopResource?.QueryInterface<Texture2D>())
+            {
+                _mDevice.ImmediateContext.CopyResource(tempTexture, _desktopImageTexture);
+            }
+            desktopResource?.Dispose();
+            return false;
+        }
+
+        private void RetrieveFrameMetadata(DesktopFrame frame)
+        {
+            if (_frameInfo.TotalMetadataBufferSize > 0)
+            {
+                // Get moved regions
+                var movedRegionsLength = 0;
+                var movedRectangles = new OutputDuplicateMoveRectangle[_frameInfo.TotalMetadataBufferSize];
+                _mDeskDupl.GetFrameMoveRects(movedRectangles.Length, movedRectangles, out movedRegionsLength);
+                frame.MovedRegions =
+                    new MovedRegion[movedRegionsLength / Marshal.SizeOf(typeof(OutputDuplicateMoveRectangle))];
+                for (var i = 0; i < frame.MovedRegions.Length; i++)
+                {
+                    var destRect = (Rectangle) movedRectangles[i].DestinationRect;
+                    frame.MovedRegions[i] = new MovedRegion
+                    {
+                        Source = new Point(movedRectangles[i].SourcePoint.X, movedRectangles[i].SourcePoint.Y),
+                        Destination =
+                            new System.Drawing.Rectangle(destRect.X, destRect.Y, destRect.Width, destRect.Height)
+                    };
+                }
+
+                // Get dirty regions
+                var dirtyRegionsLength = 0;
+                var dirtyRectangles = new RawRectangle[_frameInfo.TotalMetadataBufferSize];
+                _mDeskDupl.GetFrameDirtyRects(dirtyRectangles.Length, dirtyRectangles, out dirtyRegionsLength);
+                frame.UpdatedRegions =
+                    new System.Drawing.Rectangle[dirtyRegionsLength / Marshal.SizeOf(typeof(Rectangle))];
+                frame.FinishedRegions = new FinishedRegions[frame.UpdatedRegions.Length];
+                for (var i = 0; i < frame.UpdatedRegions.Length; i++)
+                {
+                    var dirtyRect = (Rectangle) dirtyRectangles[i];
+                    var rect = new System.Drawing.Rectangle(dirtyRect.X, dirtyRect.Y, dirtyRect.Width,
+                        dirtyRect.Height);
+
+
+                    frame.FinishedRegions[i] = new FinishedRegions
+                    {
+                        Destination = rect,
+                        Frame = ExtractRect(rect.X, rect.Y, rect.Width, rect.Height)
+                    };
+                }
+            }
+            else
+            {
+                frame.MovedRegions = new MovedRegion[0];
+                frame.UpdatedRegions = new System.Drawing.Rectangle[0];
+            }
+        }
+
+
+        private Bitmap ExtractRect(int originX, int originY, int width, int height)
+        {
+            // Get the desktop capture screenTexture
+            var mapSource = _mDevice.ImmediateContext.MapSubresource(_desktopImageTexture, 0, MapMode.Read,
+                MapFlags.None);
+
+            // Create Drawing.Bitmap
+
+            var bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); //不能是ARGB
+            var boundsRect = new System.Drawing.Rectangle(0, 0, width, height);
+
+            // Copy pixels from screen capture Texture to GDI bitmap
+            var mapDest = bitmap.LockBits(boundsRect, ImageLockMode.WriteOnly, bitmap.PixelFormat);
+            var sourcePtr = mapSource.DataPointer;
+            var destPtr = mapDest.Scan0;
+
+            sourcePtr = IntPtr.Add(sourcePtr, originY * mapSource.RowPitch + originX * 4);
+            for (var y = 0; y < height; y++)
+            {
+                // Copy a single line 
+
+                SharpDX.Utilities.CopyMemory(destPtr, sourcePtr, width * 4);
+
+                // Advance pointers
+                if (y != height - 1)
+                    sourcePtr = IntPtr.Add(sourcePtr, mapSource.RowPitch);
+                destPtr = IntPtr.Add(destPtr, mapDest.Stride);
+            }
+
+            // Release source and dest locks
+            bitmap.UnlockBits(mapDest);
+            _mDevice.ImmediateContext.UnmapSubresource(_desktopImageTexture, 0);
+            return bitmap;
+        }
+
+        private void ProcessFrame(DesktopFrame frame)
+        {
+            // Get the desktop capture texture
+            var mapSource = _mDevice.ImmediateContext.MapSubresource(_desktopImageTexture, 0, MapMode.Read,
+                MapFlags.None);
+            var bounds = (Rectangle) _mOutputDesc.DesktopBounds;
+            FinalImage = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format32bppArgb);
+            var boundsRect = new System.Drawing.Rectangle(0, 0, bounds.Width, bounds.Height);
+            // Copy pixels from screen capture Texture to GDI bitmap
+            var mapDest = FinalImage.LockBits(boundsRect, ImageLockMode.WriteOnly, FinalImage.PixelFormat);
+            var sourcePtr = mapSource.DataPointer;
+            var destPtr = mapDest.Scan0;
+            for (var y = 0; y < bounds.Height; y++)
+            {
+                // Copy a single line 
+                SharpDX.Utilities.CopyMemory(destPtr, sourcePtr, bounds.Width * 4);
+
+                // Advance pointers
+                sourcePtr = IntPtr.Add(sourcePtr, mapSource.RowPitch);
+                destPtr = IntPtr.Add(destPtr, mapDest.Stride);
+            }
+
+            // Release source and dest locks
+            FinalImage.UnlockBits(mapDest);
+            _mDevice.ImmediateContext.UnmapSubresource(_desktopImageTexture, 0);
+            frame.DesktopImage = (Bitmap) FinalImage.Clone();
+        }
+
+        private void ReleaseFrame()
+        {
+            try
+            {
+                _mDeskDupl.ReleaseFrame();
+            }
+            catch (SharpDXException ex)
+            {
+                if (ex.ResultCode.Failure)
+                    throw new DesktopDuplicationException("Failed to release frame.");
+            }
+        }
+    }
 }
\ No newline at end of file
diff --git a/AgentInterface/Api/ScreenShare/DesktopDuplication/DesktopFrame.cs b/RemoteTaskServer/Api/Win32/ScreenShare/DesktopDuplication/DesktopFrame.cs
similarity index 90%
rename from AgentInterface/Api/ScreenShare/DesktopDuplication/DesktopFrame.cs
rename to RemoteTaskServer/Api/Win32/ScreenShare/DesktopDuplication/DesktopFrame.cs
index 1175568..4f3a903 100644
--- a/AgentInterface/Api/ScreenShare/DesktopDuplication/DesktopFrame.cs
+++ b/RemoteTaskServer/Api/Win32/ScreenShare/DesktopDuplication/DesktopFrame.cs
@@ -1,26 +1,23 @@
 ﻿#region
 
 using System.Drawing;
-using System.Runtime.Serialization;
 
 #endregion
 
-namespace AgentInterface.Api.ScreenShare.DesktopDuplication
+namespace UlteriusServer.Api.Win32.ScreenShare.DesktopDuplication
 {
 
     /// <summary>
     /// Provides image data, cursor data, and image metadata about the retrieved desktop frame.
     /// </summary>
-    [DataContract]
     public class DesktopFrame
     {
         /// <summary>
         ///     Gets the bitmap representing the last retrieved desktop frame. This image spans the entire bounds of the specified
         ///     monitor.
         /// </summary>
-        [DataMember]
         public Bitmap DesktopImage { get; set; }
 
 
         /// <summary>
         ///     Gets a list of the rectangles of pixels in the desktop image that the operating system moved to another location
@@ -28,56 +25,48 @@ namespace AgentInterface.Api.ScreenShare.DesktopDuplication
         /// </summary>
         /// <remarks>
         ///     To produce a visually accurate copy of the desktop, an application must first process all moved regions before it
         ///     processes updated regions.
         /// </remarks>
-        [DataMember]
         public MovedRegion[] MovedRegions { get; set; }
 
 
         /// <summary>
         /// Returns the list of non-overlapping rectangles that indicate the areas of the desktop image that the operating system updated since the last retrieved frame.
         /// </summary>
         /// <remarks>
         /// To produce a visually accurate copy of the desktop, an application must first process all moved regions before it processes updated regions.
         /// </remarks>
-        [DataMember]
         public Rectangle[] UpdatedRegions { get; set; }
 
 
         /// <summary>
         ///     The number of frames that the operating system accumulated in the desktop image surface since the last retrieved
         ///     frame.
         /// </summary>
-        [DataMember]
         public int AccumulatedFrames { get; set; }
 
         /// <summary>
         ///     Gets the location of the top-left-hand corner of the cursor. This is not necessarily the same position as the
         ///     cursor's hot spot, which is the location in the cursor that interacts with other elements on the screen.
         /// </summary>
-        [DataMember]
         public Point CursorLocation { get; set; }
 
         /// <summary>
         ///     Gets whether the cursor on the last retrieved desktop image was visible.
         /// </summary>
-        [DataMember]
         public bool CursorVisible { get; set; }
 
         /// <summary>
         ///     Gets whether the desktop image contains protected content that was already blacked out in the desktop image.
         /// </summary>
-        [DataMember]
         public bool ProtectedContentMaskedOut { get; set; }
 
         /// <summary>
         ///     Gets whether the operating system accumulated updates by coalescing updated regions. If so, the updated regions
         ///     might contain unmodified pixels.
         /// </summary>
-        [DataMember]
         public bool RectanglesCoalesced { get; set; }
 
-        [DataMember]
         public FinishedRegions[] FinishedRegions { get; set; }
     }
 }
\ No newline at end of file
diff --git a/AgentInterface/Api/ScreenShare/DesktopDuplication/FinishedRegions.cs b/RemoteTaskServer/Api/Win32/ScreenShare/DesktopDuplication/FinishedRegions.cs
similarity index 65%
rename from AgentInterface/Api/ScreenShare/DesktopDuplication/FinishedRegions.cs
rename to RemoteTaskServer/Api/Win32/ScreenShare/DesktopDuplication/FinishedRegions.cs
index 06aeceb..1305fbe 100644
--- a/AgentInterface/Api/ScreenShare/DesktopDuplication/FinishedRegions.cs
+++ b/RemoteTaskServer/Api/Win32/ScreenShare/DesktopDuplication/FinishedRegions.cs
@@ -1,21 +1,16 @@
-﻿using System;
-using System.Drawing;
-using System.Runtime.Serialization;
+﻿using System.Drawing;
 
-namespace AgentInterface.Api.ScreenShare.DesktopDuplication
+namespace UlteriusServer.Api.Win32.ScreenShare.DesktopDuplication
 {
-    [DataContract]
     public class FinishedRegions 
     {
-        [DataMember]
         public Bitmap Frame { get; internal set; }
 
         /// <summary>
         /// Gets the target region to where the operating system moved the image region.
         /// </summary>
-        [DataMember]
         public Rectangle Destination { get; internal set; }
 
         public void Dispose()
         {
             Frame?.Dispose();
diff --git a/AgentInterface/Api/ScreenShare/DesktopDuplication/MovedRegion.cs b/RemoteTaskServer/Api/Win32/ScreenShare/DesktopDuplication/MovedRegion.cs
similarity index 91%
rename from AgentInterface/Api/ScreenShare/DesktopDuplication/MovedRegion.cs
rename to RemoteTaskServer/Api/Win32/ScreenShare/DesktopDuplication/MovedRegion.cs
index 72f8e56..8bf8976 100644
--- a/AgentInterface/Api/ScreenShare/DesktopDuplication/MovedRegion.cs
+++ b/RemoteTaskServer/Api/Win32/ScreenShare/DesktopDuplication/MovedRegion.cs
@@ -1,8 +1,8 @@
 ﻿using System.Drawing;
 
-namespace AgentInterface.Api.ScreenShare.DesktopDuplication
+namespace UlteriusServer.Api.Win32.ScreenShare.DesktopDuplication
 {
     /// <summary>
     /// Describes the movement of an image rectangle within a desktop frame.
     /// </summary>
     /// <remarks>
diff --git a/AgentInterface/Api/ScreenShare/ImageUtils.cs b/RemoteTaskServer/Api/Win32/ScreenShare/ImageUtils.cs
similarity index 100%
rename from AgentInterface/Api/ScreenShare/ImageUtils.cs
rename to RemoteTaskServer/Api/Win32/ScreenShare/ImageUtils.cs
diff --git a/AgentInterface/Api/Models/DisplayInformation.cs b/RemoteTaskServer/Api/Win32/ScreenShare/Models/DisplayInformation.cs
similarity index 95%
rename from AgentInterface/Api/Models/DisplayInformation.cs
rename to RemoteTaskServer/Api/Win32/ScreenShare/Models/DisplayInformation.cs
index 062492e..1031b98 100644
--- a/AgentInterface/Api/Models/DisplayInformation.cs
+++ b/RemoteTaskServer/Api/Win32/ScreenShare/Models/DisplayInformation.cs
@@ -1,8 +1,8 @@
 ﻿using System.Collections.Generic;
 
-namespace AgentInterface.Api.Models
+namespace UlteriusServer.Api.Win32.ScreenShare.Models
 {
     public class DisplayInformation
     {
         public string FriendlyName { get; set; }
     
diff --git a/AgentInterface/Api/Models/FrameInformation.cs b/RemoteTaskServer/Api/Win32/ScreenShare/Models/FrameInformation.cs
similarity index 55%
rename from AgentInterface/Api/Models/FrameInformation.cs
rename to RemoteTaskServer/Api/Win32/ScreenShare/Models/FrameInformation.cs
index 2f9f057..6461e3a 100644
--- a/AgentInterface/Api/Models/FrameInformation.cs
+++ b/RemoteTaskServer/Api/Win32/ScreenShare/Models/FrameInformation.cs
@@ -1,23 +1,22 @@
 ﻿#region
 
 using System.Drawing;
-using System.Runtime.Serialization;
-using AgentInterface.Api.ScreenShare.DesktopDuplication;
+using UlteriusServer.Api.Win32.ScreenShare.DesktopDuplication;
 
 #endregion
 
-namespace AgentInterface.Api.Models
+namespace UlteriusServer.Api.Win32.ScreenShare.Models
 {
-    [DataContract]
+    
     public class FrameInformation
     {
-        [DataMember]
+      
         public Rectangle Bounds { get; set; }
-        [DataMember]
+      
         public Bitmap ScreenImage { get; set; }
-        [DataMember]
+    
         public bool UsingGpu { get; set; }
-        [DataMember]
+
         public FinishedRegions[] FinishedRegions { get; set; }
     }
 }
\ No newline at end of file
diff --git a/AgentInterface/Api/Models/ResolutionInformation.cs b/RemoteTaskServer/Api/Win32/ScreenShare/Models/ResolutionInformation.cs
similarity index 85%
rename from AgentInterface/Api/Models/ResolutionInformation.cs
rename to RemoteTaskServer/Api/Win32/ScreenShare/Models/ResolutionInformation.cs
index 9cdf86f..2e20c2e 100644
--- a/AgentInterface/Api/Models/ResolutionInformation.cs
+++ b/RemoteTaskServer/Api/Win32/ScreenShare/Models/ResolutionInformation.cs
@@ -1,6 +1,6 @@
-﻿namespace AgentInterface.Api.Models
+﻿namespace UlteriusServer.Api.Win32.ScreenShare.Models
 {
     public class ResolutionInformation
     {
         public int Width { get; set; }
         public int Height { get; set; }
diff --git a/AgentInterface/Api/ScreenShare/ScreenData.cs b/RemoteTaskServer/Api/Win32/ScreenShare/ScreenData.cs
similarity index 97%
rename from AgentInterface/Api/ScreenShare/ScreenData.cs
rename to RemoteTaskServer/Api/Win32/ScreenShare/ScreenData.cs
index 2bff67a..83f43b1 100644
--- a/AgentInterface/Api/ScreenShare/ScreenData.cs
+++ b/RemoteTaskServer/Api/Win32/ScreenShare/ScreenData.cs
@@ -2,19 +2,18 @@
 
 using System;
 using System.Drawing;
 using System.Drawing.Imaging;
 using System.IO;
-using AgentInterface.Api.Models;
-using AgentInterface.Api.ScreenShare.DesktopDuplication;
-using AgentInterface.Api.Win32;
-using AgentInterface.Settings;
 using TurboJpegWrapper;
+using UlteriusServer.Api.Win32.ScreenShare.DesktopDuplication;
+using UlteriusServer.Api.Win32.ScreenShare.Models;
+using UlteriusServer.Utilities;
 
 #endregion
 
-namespace AgentInterface.Api.ScreenShare
+namespace UlteriusServer.Api.Win32.ScreenShare
 {
     public static class ScreenData
     {
         public static int ActiveDisplay = 0;
         public static Bitmap NewBitmap = new Bitmap(1, 1);
@@ -255,11 +254,11 @@ namespace AgentInterface.Api.ScreenShare
             {
                 frame = _desktopDuplicator.GetLatestFrame();
             }
             catch (Exception)
             {
-                _desktopDuplicator = new DesktopDuplicator();
+                _desktopDuplicator = new DesktopDuplicator(0);
             }
             return frame;
         }
 
 
@@ -373,18 +372,19 @@ namespace AgentInterface.Api.ScreenShare
                 Console.WriteLine("Cannot use GPU for Screen Share");
                 return;
             }
             try
             {
-                _desktopDuplicator = new DesktopDuplicator();
+                _desktopDuplicator = new DesktopDuplicator(0);
                 _nullFrame = true;
                 CanUseGpuAcceleration = true;
                 Console.WriteLine("desktop duplication setup");
             }
             catch (Exception ex)
             {
                 CanUseGpuAcceleration = false;
+                Console.WriteLine("desktop duplication failed");
                 Console.WriteLine(ex.Message);
             }
         }
 
         public class ScreenModel : IDisposable
diff --git a/AgentInterface/Api/Win32/SessionInfo.cs b/RemoteTaskServer/Api/Win32/SessionInfo.cs
similarity index 99%
rename from AgentInterface/Api/Win32/SessionInfo.cs
rename to RemoteTaskServer/Api/Win32/SessionInfo.cs
index cb87d07..508048d 100644
--- a/AgentInterface/Api/Win32/SessionInfo.cs
+++ b/RemoteTaskServer/Api/Win32/SessionInfo.cs
@@ -3,11 +3,11 @@
 using System;
 using System.Runtime.InteropServices;
 
 #endregion
 
-namespace AgentInterface.Api.Win32
+namespace UlteriusServer.Api.Win32
 {
     public static class SessionInfo
     {
         public enum LockState
         {
diff --git a/AgentInterface/Api/Win32/Win32Exception.cs b/RemoteTaskServer/Api/Win32/Win32Exception.cs
similarity index 99%
rename from AgentInterface/Api/Win32/Win32Exception.cs
rename to RemoteTaskServer/Api/Win32/Win32Exception.cs
index 94d92be..88a088e 100644
--- a/AgentInterface/Api/Win32/Win32Exception.cs
+++ b/RemoteTaskServer/Api/Win32/Win32Exception.cs
@@ -7,11 +7,11 @@ using System.Security;
 using System.Security.Permissions;
 using System.Text;
 
 #endregion
 
-namespace AgentInterface.Api.Win32
+namespace UlteriusServer.Api.Win32
 {
     [SuppressUnmanagedCodeSecurity]
     [HostProtection(SecurityAction.LinkDemand, SharedState = true)]
     [Serializable]
     internal class Win32Exception : ExternalException
diff --git a/AgentInterface/Api/Win32/WinApi.cs b/RemoteTaskServer/Api/Win32/WinApi.cs
similarity index 99%
rename from AgentInterface/Api/Win32/WinApi.cs
rename to RemoteTaskServer/Api/Win32/WinApi.cs
index ea39397..e8806a0 100644
--- a/AgentInterface/Api/Win32/WinApi.cs
+++ b/RemoteTaskServer/Api/Win32/WinApi.cs
@@ -7,11 +7,11 @@ using System.Windows.Forms;
 using System.Windows.Input;
 using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;
 
 #endregion
 
-namespace AgentInterface.Api.Win32
+namespace UlteriusServer.Api.Win32
 {
     public class WinApi
     {
 
 
diff --git a/AgentInterface/Api/Win32/WindowsIdentityImpersonator.cs b/RemoteTaskServer/Api/Win32/WindowsIdentityImpersonator.cs
similarity index 98%
rename from AgentInterface/Api/Win32/WindowsIdentityImpersonator.cs
rename to RemoteTaskServer/Api/Win32/WindowsIdentityImpersonator.cs
index 1e4a773..6b31eac 100644
--- a/AgentInterface/Api/Win32/WindowsIdentityImpersonator.cs
+++ b/RemoteTaskServer/Api/Win32/WindowsIdentityImpersonator.cs
@@ -4,11 +4,11 @@ using System.Runtime.InteropServices;
 using System.Security;
 using System.Security.Permissions;
 using System.Security.Principal;
 using Microsoft.Win32.SafeHandles;
 
-namespace AgentInterface.Api.Win32
+namespace UlteriusServer.Api.Win32
 {
     /// Impersonates a windows identity.
     /// Based on: http://msdn.microsoft.com/en-us/library/w070t6ka.aspx
     public class WindowsIdentityImpersonator : IDisposable
     {
diff --git a/RemoteTaskServer/App.config b/RemoteTaskServer/App.config
index a80256e..beda779 100644
--- a/RemoteTaskServer/App.config
+++ b/RemoteTaskServer/App.config
@@ -1,72 +1,72 @@
-﻿<?xml version="1.0" encoding="utf-8"?>
-<configuration>
-  <configSections>
-    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
-    
-  </configSections>
-  <system.net>
-    <settings>
-      <httpWebRequest useUnsafeHeaderParsing="true" />
-    </settings>
-  </system.net>
-  <startup>
-    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
-  </startup>
-  <runtime>
-    <loadFromRemoteSources enabled="true" />
-    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
-      <dependentAssembly>
-        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
-      </dependentAssembly>
-      <dependentAssembly>
-        <assemblyIdentity name="AForge.Video" publicKeyToken="cbfb6e07d173c401" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-2.2.5.0" newVersion="2.2.5.0" />
-      </dependentAssembly>
-      <dependentAssembly>
-        <assemblyIdentity name="Magnum" publicKeyToken="b800c4cfcdeea87b" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-2.1.3.0" newVersion="2.1.3.0" />
-      </dependentAssembly>
-      <dependentAssembly>
-        <assemblyIdentity name="vtortola.WebSockets" publicKeyToken="7f78616efb4a208d" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-2.2.1.0" newVersion="2.2.1.0" />
-      </dependentAssembly>
-      <dependentAssembly>
-        <assemblyIdentity name="vtortola.WebSockets.Rfc6455" publicKeyToken="7f78616efb4a208d" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-2.2.1.0" newVersion="2.2.1.0" />
-      </dependentAssembly>
-      <dependentAssembly>
-        <assemblyIdentity name="vtortola.WebSockets.Deflate" publicKeyToken="7f78616efb4a208d" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-2.2.1.0" newVersion="2.2.1.0" />
-      </dependentAssembly>
-      <dependentAssembly>
-        <assemblyIdentity name="AForge" publicKeyToken="c1db6ff4eaa06aeb" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-2.2.5.0" newVersion="2.2.5.0" />
-      </dependentAssembly>
-      <dependentAssembly>
-        <assemblyIdentity name="System.Threading.Tasks.Dataflow" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-4.6.1.0" newVersion="4.6.1.0" />
-      </dependentAssembly>
-      <dependentAssembly>
-        <assemblyIdentity name="SharpDX" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-3.0.2.0" newVersion="3.0.2.0" />
-      </dependentAssembly>
-      <dependentAssembly>
-        <assemblyIdentity name="SharpDX.DXGI" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-3.0.2.0" newVersion="3.0.2.0" />
-      </dependentAssembly>
-    </assemblyBinding>
-  </runtime>
-  <entityFramework>
-    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
-      <parameters>
-        <parameter value="v13.0" />
-      </parameters>
-    </defaultConnectionFactory>
-    <providers>
-      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
-      <provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
-    </providers>
-  </entityFramework>
-  
+﻿<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+  <configSections>
+    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
+    
+  </configSections>
+  <system.net>
+    <settings>
+      <httpWebRequest useUnsafeHeaderParsing="true" />
+    </settings>
+  </system.net>
+  <startup>
+    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
+  </startup>
+  <runtime>
+    <loadFromRemoteSources enabled="true" />
+    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+      <dependentAssembly>
+        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="AForge.Video" publicKeyToken="cbfb6e07d173c401" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-2.2.5.0" newVersion="2.2.5.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Magnum" publicKeyToken="b800c4cfcdeea87b" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-2.1.3.0" newVersion="2.1.3.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="vtortola.WebSockets" publicKeyToken="7f78616efb4a208d" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-2.2.1.0" newVersion="2.2.1.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="vtortola.WebSockets.Rfc6455" publicKeyToken="7f78616efb4a208d" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-2.2.1.0" newVersion="2.2.1.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="vtortola.WebSockets.Deflate" publicKeyToken="7f78616efb4a208d" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-2.2.1.0" newVersion="2.2.1.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="AForge" publicKeyToken="c1db6ff4eaa06aeb" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-2.2.5.0" newVersion="2.2.5.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="System.Threading.Tasks.Dataflow" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-4.6.2.0" newVersion="4.6.2.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="SharpDX" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-3.0.2.0" newVersion="3.0.2.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="SharpDX.DXGI" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-3.0.2.0" newVersion="3.0.2.0" />
+      </dependentAssembly>
+    </assemblyBinding>
+  </runtime>
+  <entityFramework>
+    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
+      <parameters>
+        <parameter value="v13.0" />
+      </parameters>
+    </defaultConnectionFactory>
+    <providers>
+      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
+      <provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
+    </providers>
+  </entityFramework>
+  
 </configuration>
\ No newline at end of file
diff --git a/RemoteTaskServer/FodyWeavers.xml b/RemoteTaskServer/FodyWeavers.xml
deleted file mode 100644
index dd5af76..0000000
--- a/RemoteTaskServer/FodyWeavers.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-﻿<?xml version="1.0" encoding="utf-8"?>
-<Weavers>
-  <Costura>
-    <ExcludeAssemblies>
-      WindowsInput
-      AgentInterface
-      Newtonsoft.Json
-    </ExcludeAssemblies>
-  </Costura>
-</Weavers>
\ No newline at end of file
diff --git a/RemoteTaskServer/Forms/Utilities/UlteriusTray.cs b/RemoteTaskServer/Forms/Utilities/UlteriusTray.cs
index 3bed889..fa11cde 100644
--- a/RemoteTaskServer/Forms/Utilities/UlteriusTray.cs
+++ b/RemoteTaskServer/Forms/Utilities/UlteriusTray.cs
@@ -5,11 +5,10 @@ using System.Diagnostics;
 using System.IO;
 using System.Reflection;
 using System.Runtime.InteropServices;
 using System.Threading;
 using System.Windows.Forms;
-using AgentInterface.Settings;
 using UlteriusServer.Api.Services.Network;
 using UlteriusServer.Properties;
 using UlteriusServer.Utilities;
 using UlteriusServer.WebServer;
 
diff --git a/RemoteTaskServer/Program.cs b/RemoteTaskServer/Program.cs
index 5115023..308abae 100644
--- a/RemoteTaskServer/Program.cs
+++ b/RemoteTaskServer/Program.cs
@@ -5,16 +5,11 @@ using System.Diagnostics;
 using System.IO;
 using System.Linq;
 using System.Reflection;
 using System.Runtime;
 using System.Runtime.InteropServices;
-using AgentInterface.Settings;
-using Topshelf;
-using UlteriusServer.Forms.Utilities;
 using UlteriusServer.Utilities;
-using UlteriusServer.Utilities.Usage;
-
 #endregion
 
 namespace UlteriusServer
 {
     internal class Program
@@ -36,54 +31,35 @@ namespace UlteriusServer
             if (Environment.OSVersion.Version.Major >= 6)
                 SetProcessDPIAware();
             HideWindow();
             try
             {
-                if (
-                    Process.GetProcessesByName(Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location))
-                        .Count() > 1) return;
-
-                ProfileOptimization.SetProfileRoot(AppEnvironment.DataPath);
-                ProfileOptimization.StartProfile("Startup.Profile");
-
-                if (args.Length > 0)
+                if (Process.GetProcessesByName(Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location))
+                        .Count() > 1)
                 {
-                    HostFactory.Run(x => //1
-                    {
-                        x.Service<UlteriusAgent>(s => //2
-                        {
-                            s.ConstructUsing(name => new UlteriusAgent()); //3
-                            s.WhenStarted(tc => tc.Start()); //4
-                            s.WhenStopped(tc => tc.Stop());
-                            s.WhenSessionChanged((se, e, id) => { se.HandleEvent(e, id); }); //5
-                        });
-                        x.RunAsLocalSystem(); //6
-                        x.EnableSessionChanged();
-                        x.EnableServiceRecovery(r => { r.RestartService(1); });
-                        x.SetDescription("The server that powers Ulterius"); //7
-                        x.SetDisplayName("Ulterius Server"); //8
-                        x.SetServiceName("UlteriusServer"); //9
-                    });
+                    return;
                 }
-                else
+                if (!Directory.Exists(AppEnvironment.DataPath))
                 {
-                    var ulterius = new Ulterius();
-                    ulterius.Start();
-                    var hardware = new HardwareSurvey();
-                    hardware.Setup();
-                    if (Tools.RunningPlatform() == Tools.Platform.Windows)
-                        UlteriusTray.ShowTray();
-                    else
-                        Console.ReadKey(true);
+                    Directory.CreateDirectory(AppEnvironment.DataPath);
                 }
+                if (!Debugger.IsAttached)
+                {
+                    ExceptionHandler.AddGlobalHandlers();
+                    Console.WriteLine("Exception Handlers Attached");
+                }
+                ProfileOptimization.SetProfileRoot(AppEnvironment.DataPath);
+                ProfileOptimization.StartProfile("Startup.Profile");
+                var ulterius = new Ulterius();
+                ulterius.Start();
+                Console.ReadKey();
             }
             catch (Exception ex)
             {
                 Console.WriteLine("Something unexpected occured");
                 Console.WriteLine(ex.Message);
                 Console.WriteLine(ex.StackTrace);
-                Console.Read();
             }
         }
 
         #region win32
 
diff --git a/RemoteTaskServer/Properties/AssemblyInfo.cs b/RemoteTaskServer/Properties/AssemblyInfo.cs
index c633a38..dd8adff 100644
--- a/RemoteTaskServer/Properties/AssemblyInfo.cs
+++ b/RemoteTaskServer/Properties/AssemblyInfo.cs
@@ -37,7 +37,7 @@ using System.Runtime.InteropServices;
 //
 // 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.9.2.0")]
-[assembly: AssemblyFileVersion("1.9.2.0")]
\ No newline at end of file
+[assembly: AssemblyVersion("1.9.5.0")]
+[assembly: AssemblyFileVersion("1.9.5.0")]
\ No newline at end of file
diff --git a/RemoteTaskServer/TerminalServer/Messaging/TerminalControl/Handlers/InputTerminalRequestHandler.cs b/RemoteTaskServer/TerminalServer/Messaging/TerminalControl/Handlers/InputTerminalRequestHandler.cs
index cee0c06..722d51d 100644
--- a/RemoteTaskServer/TerminalServer/Messaging/TerminalControl/Handlers/InputTerminalRequestHandler.cs
+++ b/RemoteTaskServer/TerminalServer/Messaging/TerminalControl/Handlers/InputTerminalRequestHandler.cs
@@ -1,12 +1,12 @@
 ﻿#region
 
 using System;
-using AgentInterface.Settings;
 using UlteriusServer.TerminalServer.Infrastructure;
 using UlteriusServer.TerminalServer.Messaging.TerminalControl.Requests;
 using UlteriusServer.TerminalServer.Session;
+using UlteriusServer.Utilities;
 using UlteriusServer.Utilities.Security;
 
 #endregion
 
 namespace UlteriusServer.TerminalServer.Messaging.TerminalControl.Handlers
diff --git a/RemoteTaskServer/TerminalServer/Messaging/WebSocketHandler.cs b/RemoteTaskServer/TerminalServer/Messaging/WebSocketHandler.cs
index e9bd2e6..f295f68 100644
--- a/RemoteTaskServer/TerminalServer/Messaging/WebSocketHandler.cs
+++ b/RemoteTaskServer/TerminalServer/Messaging/WebSocketHandler.cs
@@ -8,10 +8,11 @@ using MassTransit;
 using UlteriusServer.TerminalServer.Infrastructure;
 using UlteriusServer.TerminalServer.Messaging.Connection;
 using UlteriusServer.TerminalServer.Messaging.Serialization;
 using UlteriusServer.TerminalServer.Session;
 using vtortola.WebSockets;
+using ILogger = UlteriusServer.TerminalServer.Infrastructure.ILogger;
 
 #endregion
 
 namespace UlteriusServer.TerminalServer.Messaging
 {
@@ -71,22 +72,22 @@ namespace UlteriusServer.TerminalServer.Messaging
                     var queueRequest = _serializer.Deserialize(connectionId, msg, out type);
                     if (queueRequest == null)
                     {
                         continue;
                     }
-                    Console.WriteLine(queueRequest);
+              
                     queueRequest.ConnectionId = connectionId;
 
                     _queue.Publish(queueRequest, type);
                 }
             }
             catch (Exception aex)
             {
                 _log.Error("Error Handling connection", aex.GetBaseException());
                 try
                 {
-                    _ws.Close();
+                    _ws.CloseAsync();
                 }
                 catch
                 {
                     // ignored
                 }
diff --git a/RemoteTaskServer/TerminalServer/Messaging/WebSocketQueueServer.cs b/RemoteTaskServer/TerminalServer/Messaging/WebSocketQueueServer.cs
index 423caed..fc19b86 100644
--- a/RemoteTaskServer/TerminalServer/Messaging/WebSocketQueueServer.cs
+++ b/RemoteTaskServer/TerminalServer/Messaging/WebSocketQueueServer.cs
@@ -9,10 +9,11 @@ using UlteriusServer.TerminalServer.Infrastructure;
 using UlteriusServer.TerminalServer.Messaging.Connection;
 using UlteriusServer.TerminalServer.Messaging.Serialization;
 using UlteriusServer.TerminalServer.Session;
 using vtortola.WebSockets;
 using vtortola.WebSockets.Rfc6455;
+using ILogger = UlteriusServer.TerminalServer.Infrastructure.ILogger;
 
 #endregion
 
 namespace UlteriusServer.TerminalServer.Messaging
 {
@@ -36,18 +37,17 @@ namespace UlteriusServer.TerminalServer.Messaging
             Queue = ServiceBusFactory.New(sbc =>
             {
                 sbc.UseBinarySerializer();
                 sbc.ReceiveFrom("loopback://localhost/queue");
             });
-
-            _wsServer = new WebSocketListener(endpoint, new WebSocketListenerOptions
+            var options = new WebSocketListenerOptions
             {
                 PingTimeout = Timeout.InfiniteTimeSpan,
-                OnHttpNegotiation = HttpNegotiation
-            });
-            var rfc6455 = new WebSocketFactoryRfc6455(_wsServer);
-            _wsServer.Standards.RegisterStandard(rfc6455);
+                HttpAuthenticationHandler = this.HttpNegotiation
+            };
+            options.Standards.RegisterRfc6455();
+            _wsServer = new WebSocketListener(endpoint, options);
         }
 
         public void Dispose()
         {
             _cancellation.Cancel();
@@ -56,17 +56,17 @@ namespace UlteriusServer.TerminalServer.Messaging
 
         public IServiceBus Queue { get; }
 
         public Task StartAsync()
         {
-            _wsServer.Start();
-            _log.Info("Echo Server started");
+            _wsServer.StartAsync().GetAwaiter().GetResult();
             return AcceptWebSocketClientsAsync(_wsServer);
         }
 
-        private void HttpNegotiation(WebSocketHttpRequest request, WebSocketHttpResponse response)
+        private async Task<bool> HttpNegotiation(WebSocketHttpRequest request, WebSocketHttpResponse response)
         {
+            await Task.Delay(TimeSpan.FromMilliseconds(1));
             var connectionId = Guid.Empty;
             if (request.RequestUri == null || request.RequestUri.OriginalString.Length < 1 ||
                 !Guid.TryParse(request.RequestUri.OriginalString.Substring(1), out connectionId))
             {
                 connectionId = _sysInfo.Guid();
@@ -95,12 +95,14 @@ namespace UlteriusServer.TerminalServer.Messaging
                 ctx.HandleTimeout(TimeSpan.FromSeconds(5), () => { response.Status = HttpStatusCode.RequestTimeout; });
                 ctx.Handle<ConnectionConnectResponse>(
                     res =>
                     {
                         response.Cookies.Add(new Cookie(ConnectionManager.UserSessionCookieName, res.UserId.ToString()));
+                       
                     });
             });
+            return true;
         }
 
         private async Task AcceptWebSocketClientsAsync(WebSocketListener server)
         {
             while (!_cancellation.IsCancellationRequested)
@@ -118,12 +120,13 @@ namespace UlteriusServer.TerminalServer.Messaging
                 catch (InvalidOperationException)
                 {
                 }
                 catch (Exception aex)
                 {
-                    _log.Error("Error Accepting clients", aex.GetBaseException());
+                   // _log.Error("Error Accepting clients", aex.GetBaseException());
                 }
             }
-            _log.Info("Server Stop accepting clients");
+           
+            //_log.Info("Server Stop accepting clients");
         }
     }
 }
\ No newline at end of file
diff --git a/RemoteTaskServer/Ulterius.cs b/RemoteTaskServer/Ulterius.cs
index 3ac19b4..d7e8f4a 100644
--- a/RemoteTaskServer/Ulterius.cs
+++ b/RemoteTaskServer/Ulterius.cs
@@ -2,13 +2,13 @@
 
 using System;
 using System.Diagnostics;
 using System.IO;
 using System.Reflection;
-using AgentInterface.Settings;
 using UlteriusServer.Api;
 using UlteriusServer.Api.Services.LocalSystem;
+using UlteriusServer.Api.Win32;
 using UlteriusServer.TerminalServer;
 using UlteriusServer.Utilities;
 using UlteriusServer.WebCams;
 using UlteriusServer.WebServer;
 
@@ -23,50 +23,25 @@ namespace UlteriusServer
 
         public void Start(bool serviceMode = false)
         {
             isService = serviceMode;
 
-            if (Process.GetProcessesByName(
-                Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location))
-                .Length > 1)
-            {
-                Process.GetCurrentProcess().Kill();
-            }
-            if (!Directory.Exists(AppEnvironment.DataPath))
-            {
-                Directory.CreateDirectory(AppEnvironment.DataPath);
-            }
-
-            if (!Debugger.IsAttached)
-            {
-
-                ExceptionHandler.AddGlobalHandlers();
-                Console.WriteLine("Exception Handlers Attached");
-            }
-
             Setup();
         }
 
         /// <summary>
         ///     Starts various parts of the server than loop to keep everything alive.
         /// </summary>
         private void Setup()
         {
             
 
-
+            Tools.RestartDaemon();
              Console.WriteLine("Creating settings");
-           
-            var settings = Config.Load();
-
-        
-           
+             var settings = Config.Load();
             Console.WriteLine("Configuring up server");
             Tools.ConfigureServer();
-          
-          
-        
             Console.WriteLine(Assembly.GetExecutingAssembly().GetName().Version);
             var useTerminal = settings.Terminal.AllowTerminal;
             var useWebServer = settings.WebServer.ToggleWebServer;
             var useWebCams = settings.Webcams.UseWebcams;
             if (useWebCams)
@@ -81,11 +56,15 @@ namespace UlteriusServer
             }
             systemService = new SystemService();
             Console.WriteLine("Creating system service");
             systemService.Start();
             UlteriusApiServer.RunningAsService = Tools.RunningAsService();
-            Console.Write($"Service: {UlteriusApiServer.RunningAsService}");
+            if (UlteriusApiServer.RunningAsService)
+            {
+                Console.Write($"Service: {UlteriusApiServer.RunningAsService}");
+                DesktopWatcher.Start();
+            }
             UlteriusApiServer.Start();
            
             if (useTerminal)
             {
                 Console.WriteLine("Starting Terminal API");
diff --git a/RemoteTaskServer/UlteriusAgent.cs b/RemoteTaskServer/UlteriusAgent.cs
deleted file mode 100644
index 761cf29..0000000
--- a/RemoteTaskServer/UlteriusAgent.cs
+++ /dev/null
@@ -1,82 +0,0 @@
-﻿#region
-
-using System;
-using System.Diagnostics;
-using Topshelf;
-using UlteriusServer.Utilities;
-using UlteriusServer.Utilities.Usage;
-
-#endregion
-
-namespace UlteriusServer
-{
-    public class UlteriusAgent
-    {
-
-
-        private Ulterius _ulterius;
-
-        public void Start()
-        {
-            _ulterius = new Ulterius();
-            _ulterius.Start(true);
-            HandleMonitor();
-            var hardware = new HardwareSurvey();
-            hardware.Setup(true);
-            Console.ReadLine();
-        }
-
-       
-        public void HandleMonitor()
-        {
-            Tools.RestartAgent();
-        }
-
-
-        public void Stop()
-        {
-            var agentList = Process.GetProcessesByName("UlteriusAgent");
-            foreach (var agent in agentList)
-            {
-                try
-                {
-                    agent.Kill();
-                }
-                catch (Exception)
-                {
-                    // ignored
-                }
-            }
-            var managerList = Process.GetProcessesByName("DaemonManager");
-            foreach (var manager in managerList)
-            {
-                try
-                {
-                    manager.Kill();
-                }
-                catch (Exception)
-                {
-                    // ignored
-                }
-            }
-
-            var serverInstanceList = Process.GetProcessesByName("Ulterius Server");
-            foreach (var server in serverInstanceList)
-            {
-                try
-                {
-                    server.Kill();
-                }
-                catch (Exception)
-                {
-                    // ignored
-                }
-            }
-        }
-
-        public void HandleEvent(HostControl hostControl, SessionChangedArguments arg3)
-        {
-            HandleMonitor();
-        }
-    }
-}
\ No newline at end of file
diff --git a/RemoteTaskServer/UlteriusServer.csproj b/RemoteTaskServer/UlteriusServer.csproj
index a0dcfcb..e6ca98d 100644
--- a/RemoteTaskServer/UlteriusServer.csproj
+++ b/RemoteTaskServer/UlteriusServer.csproj
@@ -1,461 +1,437 @@
-﻿<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="..\packages\Microsoft.Net.Compilers.2.0.0-rc3\build\Microsoft.Net.Compilers.props" Condition="Exists('..\packages\Microsoft.Net.Compilers.2.0.0-rc3\build\Microsoft.Net.Compilers.props')" />
-  <Import Project="..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.3\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props" Condition="Exists('..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.3\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" />
-  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
-  <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProjectGuid>{E9A365D5-AEBE-4AF3-86C5-D17BC65ADE46}</ProjectGuid>
-    <OutputType>Exe</OutputType>
-    <AppDesignerFolder>Properties</AppDesignerFolder>
-    <RootNamespace>UlteriusServer</RootNamespace>
-    <AssemblyName>Ulterius Server</AssemblyName>
-    <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
-    <FileAlignment>512</FileAlignment>
-    <NuGetPackageImportStamp>
-    </NuGetPackageImportStamp>
-    <TargetFrameworkProfile />
-    <IsWebBootstrapper>false</IsWebBootstrapper>
-    <PublishUrl>publish\</PublishUrl>
-    <Install>true</Install>
-    <InstallFrom>Disk</InstallFrom>
-    <UpdateEnabled>false</UpdateEnabled>
-    <UpdateMode>Foreground</UpdateMode>
-    <UpdateInterval>7</UpdateInterval>
-    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
-    <UpdatePeriodically>false</UpdatePeriodically>
-    <UpdateRequired>false</UpdateRequired>
-    <MapFileExtensions>true</MapFileExtensions>
-    <ApplicationRevision>0</ApplicationRevision>
-    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
-    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
-    <UseApplicationTrust>false</UseApplicationTrust>
-    <BootstrapperEnabled>true</BootstrapperEnabled>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <PlatformTarget>AnyCPU</PlatformTarget>
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <Prefer32Bit>false</Prefer32Bit>
-    <LangVersion>6</LangVersion>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <PlatformTarget>AnyCPU</PlatformTarget>
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <LangVersion>6</LangVersion>
-    <Prefer32Bit>false</Prefer32Bit>
-    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
-  </PropertyGroup>
-  <PropertyGroup />
-  <PropertyGroup />
-  <PropertyGroup />
-  <PropertyGroup>
-    <ApplicationManifest>app.manifest</ApplicationManifest>
-  </PropertyGroup>
-  <PropertyGroup>
-    <ApplicationIcon>256.ico</ApplicationIcon>
-  </PropertyGroup>
-  <PropertyGroup>
-    <StartupObject />
-  </PropertyGroup>
-  <PropertyGroup>
-    <SignAssembly>false</SignAssembly>
-  </PropertyGroup>
-  <PropertyGroup>
-    <AssemblyOriginatorKeyFile>
-    </AssemblyOriginatorKeyFile>
-  </PropertyGroup>
-  <PropertyGroup>
-    <SignManifests>false</SignManifests>
-  </PropertyGroup>
-  <ItemGroup>
-    <Compile Include="Api\Network\Messages\MessageResolver.cs" />
-    <Compile Include="Api\Network\Messages\PacketLoader.cs" />
-    <Compile Include="Api\Network\Messages\RectangleConverter.cs" />
-    <Compile Include="Api\Network\Models\FanInformation.cs" />
-    <Compile Include="Api\Network\Models\LoginInformation.cs" />
-    <Compile Include="Api\Network\PacketHandlers\DisplayPacketHandler.cs" />
-    <Compile Include="Api\Network\UlteriusAgentClient.cs" />
-    <Compile Include="Api\Services\LocalSystem\Daemons\JobModel.cs" />
-    <Compile Include="Api\Network\PacketHandlers\CronJobPacketHandler.cs" />
-    <Compile Include="Api\Services\LocalSystem\Daemons\CronDaemon.cs" />
-    <Compile Include="Api\Services\LocalSystem\Daemons\CronJob.cs" />
-    <Compile Include="Api\Services\LocalSystem\Daemons\CronSchedule.cs" />
-    <Compile Include="Api\Services\LocalSystem\CronJobService.cs" />
-    <Compile Include="Api\Services\Update\UpdateService.cs" />
-    <Compile Include="Api\Network\Messages\Message.cs" />
-    <Compile Include="Api\Network\Messages\MessageQueueManager.cs" />
-    <Compile Include="Api\Services\LocalSystem\FileSearchService.cs" />
-    <Compile Include="Forms\Utilities\AboutBox.cs">
-      <SubType>Form</SubType>
-    </Compile>
-    <Compile Include="Forms\Utilities\AboutBox.Designer.cs">
-      <DependentUpon>AboutBox.cs</DependentUpon>
-    </Compile>
-    <Compile Include="TerminalServer\Infrastructure\ILogger.cs" />
-    <Compile Include="TerminalServer\Infrastructure\Log4NetLogger.cs" />
-    <Compile Include="Ulterius.cs" />
-    <Compile Include="UlteriusAgent.cs" />
-    <Compile Include="Utilities\Drive\PartitionModel.cs" />
-    <Compile Include="Utilities\Drive\SmartData.cs" />
-    <Compile Include="Utilities\Drive\SmartEnums.cs" />
-    <Compile Include="Utilities\Drive\SmartModel.cs" />
-    <Compile Include="Utilities\Extensions\NetworkBrowser.cs" />
-    <Compile Include="Utilities\Extensions\TaskExtensions.cs" />
-    <Compile Include="Utilities\Files\Database\DatabaseController.cs" />
-    <Compile Include="Utilities\Files\Database\DatabaseManager.cs" />
-    <Compile Include="Utilities\Security\Streams\OfbStream.cs" />
-    <Compile Include="Utilities\Security\Streams\ZeroStream.cs" />
-    <Compile Include="Utilities\Security\AuthUtils.cs" />
-    <Compile Include="Utilities\Usage\HardwareSurvey.cs" />
-    <Compile Include="WebCams\WebCamManager.cs" />
-    <Compile Include="WebSocketAPI\Authentication\AuthClient.cs" />
-    <Compile Include="Forms\Utilities\UlteriusTray.cs" />
-    <Compile Include="Api\Network\Messages\Packet.cs" />
-    <Compile Include="Api\Network\Messages\MessageBuilder.cs" />
-    <Compile Include="Api\Network\PacketHandler.cs" />
-    <Compile Include="Api\Network\PacketHandlers\ErrorPacketHandler.cs" />
-    <Compile Include="Api\Network\PacketManager.cs" />
-    <Compile Include="Api\Network\PacketHandlers\WebCamPacketHandler.cs" />
-    <Compile Include="Api\Network\PacketHandlers\FilePacketHandler.cs" />
-    <Compile Include="Api\Network\PacketHandlers\GpuPacketHandler.cs" />
-    <Compile Include="Api\Network\PacketHandlers\ScreenSharePacketHandler.cs" />
-    <Compile Include="Api\Network\PacketHandlers\AccountPacketHandler.cs" />
-    <Compile Include="Api\Network\PacketHandlers\SettingsPacketHandler.cs" />
-    <Compile Include="Api\Network\PacketHandlers\NetworkPacketHandler.cs" />
-    <Compile Include="Api\Network\PacketHandlers\CpuPacketHandler.cs" />
-    <Compile Include="Api\Network\PacketHandlers\OperatingSystemPacketHandler.cs" />
-    <Compile Include="Api\Network\PacketHandlers\ProcessPacketHandler.cs" />
-    <Compile Include="Api\Network\PacketHandlers\ServerPacketHandler.cs" />
-    <Compile Include="Api\Network\PacketHandlers\SystemPacketHandler.cs" />
-    <Compile Include="Api\Network\Models\GpuInformation.cs" />
-    <Compile Include="Api\Services\LocalSystem\ScreenShareService.cs" />
-    <Compile Include="TerminalServer\Cli\CommandSession.cs" />
-    <Compile Include="TerminalServer\Cli\PowerShellSession.cs" />
-    <Compile Include="TerminalServer\Cli\_ICliSession.cs" />
-    <Compile Include="TerminalServer\Cli\_ICliSessionFactory.cs" />
-    <Compile Include="TerminalServer\Infrastructure\SystemInfo.cs" />
-    <Compile Include="TerminalServer\Infrastructure\_ISystemInfo.cs" />
-    <Compile Include="TerminalServer\Messaging\Connection\ConnectionConnectRequest.cs" />
-    <Compile Include="TerminalServer\Messaging\Connection\IConnectionEvent.cs" />
-    <Compile Include="TerminalServer\Messaging\Connection\IConnectionRequest.cs" />
-    <Compile Include="TerminalServer\Messaging\IMessageBus.cs" />
-    <Compile Include="TerminalServer\Messaging\Serialization\DefaultEventSerializator.cs" />
-    <Compile Include="TerminalServer\Messaging\Serialization\IEventSerializator.cs" />
-    <Compile Include="TerminalServer\Messaging\TerminalControl\Events\ClosedTerminalEvent.cs" />
-    <Compile Include="TerminalServer\Messaging\TerminalControl\Events\CreatedTerminalEvent.cs" />
-    <Compile Include="TerminalServer\Messaging\TerminalControl\Events\SessionStateEvent.cs" />
-    <Compile Include="TerminalServer\Messaging\TerminalControl\Events\TerminalOutputEvent.cs" />
-    <Compile Include="TerminalServer\Messaging\TerminalControl\Events\_ITerminalEvent.cs" />
-    <Compile Include="TerminalServer\Messaging\TerminalControl\Handlers\AesHandshakeRequestHandler.cs" />
-    <Compile Include="TerminalServer\Messaging\TerminalControl\Handlers\CloseTerminalRequestHandler.cs" />
-    <Compile Include="TerminalServer\Messaging\TerminalControl\Handlers\CreateTerminalRequestHandler.cs" />
-    <Compile Include="TerminalServer\Messaging\TerminalControl\Handlers\InputTerminalRequestHandler.cs" />
-    <Compile Include="TerminalServer\Messaging\TerminalControl\Handlers\_IRequestHandler.cs" />
-    <Compile Include="TerminalServer\Messaging\TerminalControl\Requests\AesHandshakeRequest.cs" />
-    <Compile Include="TerminalServer\Messaging\TerminalControl\Requests\CloseTerminalRequest.cs" />
-    <Compile Include="TerminalServer\Messaging\TerminalControl\Requests\CreateTerminalRequest.cs" />
-    <Compile Include="TerminalServer\Messaging\TerminalControl\Requests\TerminalInputRequest.cs" />
-    <Compile Include="TerminalServer\Messaging\TerminalControl\Requests\_TerminalControlRequest.cs" />
-    <Compile Include="TerminalServer\Messaging\WebSocketHandler.cs" />
-    <Compile Include="TerminalServer\Messaging\WebSocketQueueServer.cs" />
-    <Compile Include="TerminalServer\Session\ConnectionManager.cs" />
-    <Compile Include="TerminalServer\Session\UserConnection.cs" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="Api\UlteriusApiServer.cs" />
-    <Compile Include="TerminalServer\TerminalManagerServer.cs" />
-    <Compile Include="Utilities\DynamicMap.cs" />
-    <Compile Include="Utilities\Extensions\StringExtensions.cs" />
-    <Compile Include="Utilities\Files\FileManager.cs" />
-    <Compile Include="Utilities\IconTools.cs" />
-    <Compile Include="Utilities\Security\UlteriusAes.cs" />
-    <Compile Include="Utilities\Security\Rsa.cs" />
-    <Compile Include="Utilities\Files\FileTree.cs" />
-    <Compile Include="Utilities\Trace.cs" />
-    <Compile Include="WebServer\MultipartParser.cs" />
-    <Compile Include="WebSocketAPI\Authentication\CookieManager.cs" />
-    <Compile Include="WebSocketAPI\WebSocketEventListener.cs" />
-    <Compile Include="Api\Network\Models\DriveInformation.cs" />
-    <Compile Include="Api\Network\Models\SystemInformation.cs" />
-    <Compile Include="Api\Network\Models\NetworkInformation.cs" />
-    <Compile Include="Api\Network\Models\CpuInformation.cs" />
-    <Compile Include="Api\Network\Models\OperatingSystemInformation.cs" />
-    <Compile Include="Program.cs" />
-    <Compile Include="Properties\Resources.Designer.cs">
-      <AutoGen>True</AutoGen>
-      <DesignTime>True</DesignTime>
-      <DependentUpon>Resources.resx</DependentUpon>
-    </Compile>
-    <Compile Include="Api\Network\Models\ProcessInformation.cs" />
-    <Compile Include="Properties\AssemblyInfo.cs" />
-    <Compile Include="Utilities\ExceptionHandler.cs" />
-    <Compile Include="Api\Services\Network\NetworkService.cs" />
-    <Compile Include="Api\Services\LocalSystem\SystemService.cs" />
-    <Compile Include="Utilities\Tools.cs" />
-    <Compile Include="WebServer\HttpServer.cs" />
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="App.config" />
-    <None Include="app.manifest" />
-    <None Include="App1.config" />
-    <None Include="packages.config" />
-  </ItemGroup>
-  <ItemGroup>
-    <EmbeddedResource Include="Forms\Utilities\AboutBox.resx">
-      <DependentUpon>AboutBox.cs</DependentUpon>
-    </EmbeddedResource>
-    <EmbeddedResource Include="Properties\Resources.resx">
-      <Generator>ResXFileCodeGenerator</Generator>
-      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
-      <SubType>Designer</SubType>
-    </EmbeddedResource>
-  </ItemGroup>
-  <ItemGroup>
-    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
-      <Visible>False</Visible>
-      <ProductName>.NET Framework 3.5 SP1</ProductName>
-      <Install>false</Install>
-    </BootstrapperPackage>
-  </ItemGroup>
-  <ItemGroup>
-    <Content Include="256.ico" />
-    <EmbeddedResource Include="Packets.json" />
-    <None Include="Resources\ApplicationIcon.ico" />
-    <None Include="FodyWeavers.xml">
-      <SubType>Designer</SubType>
-    </None>
-    <Content Include="twitter-profile.ico" />
-  </ItemGroup>
-  <ItemGroup>
-    <WCFMetadata Include="Service References\" />
-  </ItemGroup>
-  <ItemGroup>
-    <Folder Include="bin\Debug\" />
-    <Folder Include="Utilities\Files\Models\" />
-  </ItemGroup>
-  <ItemGroup>
-    <Reference Include="AForge, Version=2.2.5.0, Culture=neutral, PublicKeyToken=c1db6ff4eaa06aeb, processorArchitecture=MSIL">
-      <HintPath>..\packages\AForge.2.2.5\lib\AForge.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="AForge.Imaging, Version=2.2.5.0, Culture=neutral, PublicKeyToken=ba8ddea9676ca48b, processorArchitecture=MSIL">
-      <HintPath>..\packages\AForge.Imaging.2.2.5\lib\AForge.Imaging.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="AForge.Math, Version=2.2.5.0, Culture=neutral, PublicKeyToken=abba2e25397ee8c9, processorArchitecture=MSIL">
-      <HintPath>..\packages\AForge.Math.2.2.5\lib\AForge.Math.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="AForge.Video, Version=2.2.5.0, Culture=neutral, PublicKeyToken=cbfb6e07d173c401, processorArchitecture=MSIL">
-      <HintPath>..\packages\AForge.Video.2.2.5\lib\AForge.Video.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="AForge.Video.DirectShow, Version=2.2.5.0, Culture=neutral, PublicKeyToken=61ea4348d43881b7, processorArchitecture=MSIL">
-      <HintPath>..\packages\AForge.Video.DirectShow.2.2.5\lib\AForge.Video.DirectShow.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="AForge.Vision, Version=2.2.5.0, Culture=neutral, PublicKeyToken=b612fa915eefaa06, processorArchitecture=MSIL">
-      <HintPath>..\packages\AForge.Vision.2.2.5\lib\AForge.Vision.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="BouncyCastle.Crypto, Version=1.8.1.0, Culture=neutral, PublicKeyToken=0e99375e54769942">
-      <HintPath>..\packages\BouncyCastle.1.8.1\lib\BouncyCastle.Crypto.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="DotNetZip, Version=1.10.1.0, Culture=neutral, PublicKeyToken=6583c7c814667745, processorArchitecture=MSIL">
-      <HintPath>..\packages\DotNetZip.1.10.1\lib\net20\DotNetZip.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="log4net, Version=2.0.7.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
-      <HintPath>..\packages\log4net.2.0.7\lib\net45-full\log4net.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="Magnum, Version=2.1.3.0, Culture=neutral, PublicKeyToken=b800c4cfcdeea87b, processorArchitecture=MSIL">
-      <HintPath>..\packages\Magnum.2.1.3\lib\NET40\Magnum.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="MassTransit, Version=2.9.0.0, Culture=neutral, PublicKeyToken=b8e0e9f2f1e657fa, processorArchitecture=MSIL">
-      <HintPath>..\packages\MassTransit.2.9.0\lib\net40\MassTransit.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
-      <HintPath>..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.3\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="Mono.Cecil, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
-      <HintPath>..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="Mono.Cecil.Mdb, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
-      <HintPath>..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Mdb.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="Mono.Cecil.Pdb, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
-      <HintPath>..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Pdb.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="Mono.Cecil.Rocks, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
-      <HintPath>..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Rocks.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
-      <HintPath>..\packages\Newtonsoft.Json.10.0.1-beta1\lib\net45\Newtonsoft.Json.dll</HintPath>
-    </Reference>
-    <Reference Include="Open.Nat, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f22a6a4582336c76, processorArchitecture=MSIL">
-      <HintPath>..\packages\Open.NAT.2.1.0.0\lib\net45\Open.Nat.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="PresentationCore" />
-    <Reference Include="System" />
-    <Reference Include="System.Core" />
-    <Reference Include="System.DirectoryServices" />
-    <Reference Include="System.DirectoryServices.AccountManagement" />
-    <Reference Include="System.Drawing" />
-    <Reference Include="System.IO.Compression" />
-    <Reference Include="System.Management" />
-    <Reference Include="System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\3.0\System.Management.Automation.dll</HintPath>
-    </Reference>
-    <Reference Include="System.Net" />
-    <Reference Include="System.Net.Http" />
-    <Reference Include="System.ServiceModel" />
-    <Reference Include="System.ServiceProcess" />
-    <Reference Include="System.Threading.Tasks.Dataflow, Version=4.6.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
-      <HintPath>..\packages\System.Threading.Tasks.Dataflow.4.7.0\lib\portable-net45+win8+wpa81\System.Threading.Tasks.Dataflow.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="System.Web" />
-    <Reference Include="System.Windows.Forms" />
-    <Reference Include="System.Xaml" />
-    <Reference Include="Microsoft.CSharp" />
-    <Reference Include="System.Xml" />
-    <Reference Include="Topshelf, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b800c4cfcdeea87b, processorArchitecture=MSIL">
-      <HintPath>..\packages\Topshelf.4.0.3\lib\net452\Topshelf.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="vtortola.WebSockets, Version=2.2.2.0, Culture=neutral, PublicKeyToken=7f78616efb4a208d, processorArchitecture=MSIL">
-      <HintPath>..\packages\vtortola.WebSocketListener.2.2.2.0\lib\net45\vtortola.WebSockets.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="vtortola.WebSockets.Deflate, Version=2.2.2.0, Culture=neutral, PublicKeyToken=7f78616efb4a208d, processorArchitecture=MSIL">
-      <HintPath>..\packages\vtortola.WebSocketListener.2.2.2.0\lib\net45\vtortola.WebSockets.Deflate.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="vtortola.WebSockets.Rfc6455, Version=2.2.2.0, Culture=neutral, PublicKeyToken=7f78616efb4a208d, processorArchitecture=MSIL">
-      <HintPath>..\packages\vtortola.WebSocketListener.2.2.2.0\lib\net45\vtortola.WebSockets.Rfc6455.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="WindowsBase" />
-    <Reference Include="ZetaLongPaths, Version=1.0.0.14, Culture=neutral, PublicKeyToken=b764f59068f31f38, processorArchitecture=MSIL">
-      <HintPath>..\packages\ZetaLongPaths.1.0.0.14\lib\net40-full\ZetaLongPaths.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-  </ItemGroup>
-  <ItemGroup>
-    <COMReference Include="NetFwTypeLib">
-      <Guid>{58FBCF7C-E7A9-467C-80B3-FC65E8FCCA08}</Guid>
-      <VersionMajor>1</VersionMajor>
-      <VersionMinor>0</VersionMinor>
-      <Lcid>0</Lcid>
-      <WrapperTool>tlbimp</WrapperTool>
-      <Isolated>False</Isolated>
-      <EmbedInteropTypes>True</EmbedInteropTypes>
-    </COMReference>
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="..\..\inputsimulator2\WindowsInput\WindowsInput.csproj">
-      <Project>{3549cd6f-80f8-450f-b99e-cf0a736b1f2a}</Project>
-      <Name>WindowsInput</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\AgentInterface\AgentInterface.csproj">
-      <Project>{5c3b0b17-cbb7-4b4b-b527-1fab2bb96466}</Project>
-      <Name>AgentInterface</Name>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
-  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
-    <PropertyGroup>
-      <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
-    </PropertyGroup>
-    <Error Condition="!Exists('..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.3\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.3\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props'))" />
-    <Error Condition="!Exists('..\packages\Microsoft.Net.Compilers.2.0.0-rc3\build\Microsoft.Net.Compilers.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Net.Compilers.2.0.0-rc3\build\Microsoft.Net.Compilers.props'))" />
-    <Error Condition="!Exists('..\packages\Fody.1.29.3\build\dotnet\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Fody.1.29.3\build\dotnet\Fody.targets'))" />
-    <Error Condition="!Exists('..\packages\Costura.Fody.2.0.0-beta0018\build\Costura.Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Costura.Fody.2.0.0-beta0018\build\Costura.Fody.targets'))" />
-  </Target>
-  <PropertyGroup>
-    <PostBuildEvent>
-    </PostBuildEvent>
-  </PropertyGroup>
-  <PropertyGroup>
-    <PreBuildEvent>
-    </PreBuildEvent>
-  </PropertyGroup>
-  <Target Name="AfterClean">
-    <Delete Files="$(TargetDir)\*.dll" />
-  </Target>
-  <Target Name="AfterClean">
-    <ItemGroup>
-      <FilesToDelete Include="$(TargetDir)\*.dll" />
-    </ItemGroup>
-    <Delete Files="@(FilesToDelete)" />
-  </Target>
-  <UsingTask TaskName="CosturaCleanup" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" TaskFactory="CodeTaskFactory">
-    <ParameterGroup>
-      <Config Output="false" Required="true" ParameterType="Microsoft.Build.Framework.ITaskItem" />
-      <Files Output="false" Required="true" ParameterType="Microsoft.Build.Framework.ITaskItem[]" />
-    </ParameterGroup>
-    <Task Evaluate="true">
-      <Reference xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Include="System.Xml" />
-      <Reference xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Include="System.Xml.Linq" />
-      <Using xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Namespace="System" />
-      <Using xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Namespace="System.IO" />
-      <Using xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Namespace="System.Xml.Linq" />
-      <Code xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Type="Fragment" Language="cs"><![CDATA[
-var config = XElement.Load(Config.ItemSpec).Elements("Costura").FirstOrDefault();
-
-if (config == null) return true;
-
-var excludedAssemblies = new List<string>();
-var attribute = config.Attribute("ExcludeAssemblies");
-if (attribute != null)
-    foreach (var item in attribute.Value.Split('|').Select(x => x.Trim()).Where(x => x != string.Empty))
-        excludedAssemblies.Add(item);
-var element = config.Element("ExcludeAssemblies");
-if (element != null)
-    foreach (var item in element.Value.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()).Where(x => x != string.Empty))
-        excludedAssemblies.Add(item);
-
-var filesToCleanup = Files.Select(f => f.ItemSpec).Where(f => !excludedAssemblies.Contains(Path.GetFileNameWithoutExtension(f), StringComparer.InvariantCultureIgnoreCase));
-
-foreach (var item in filesToCleanup)
-  File.Delete(item);
-]]></Code>
-    </Task>
-  </UsingTask>
-  <Target Name="CleanReferenceCopyLocalPaths" AfterTargets="AfterBuild;NonWinFodyTarget">
-    <CosturaCleanup Config="FodyWeavers.xml" Files="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" />
-  </Target>
-  <Import Project="..\packages\Fody.1.29.3\build\dotnet\Fody.targets" Condition="Exists('..\packages\Fody.1.29.3\build\dotnet\Fody.targets')" />
-  <Import Project="..\packages\Costura.Fody.2.0.0-beta0018\build\Costura.Fody.targets" Condition="Exists('..\packages\Costura.Fody.2.0.0-beta0018\build\Costura.Fody.targets')" />
-  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
-       Other similar extension points exist, see Microsoft.Common.targets.
-  <Target Name="BeforeBuild">
-  </Target>
-  <Target Name="AfterBuild">
-  </Target>
-  
-  -->
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="..\packages\Microsoft.Net.Compilers.2.4.0\build\Microsoft.Net.Compilers.props" Condition="Exists('..\packages\Microsoft.Net.Compilers.2.4.0\build\Microsoft.Net.Compilers.props')" />
+  <Import Project="..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.3\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props" Condition="Exists('..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.3\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" />
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{E9A365D5-AEBE-4AF3-86C5-D17BC65ADE46}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>UlteriusServer</RootNamespace>
+    <AssemblyName>Ulterius Server</AssemblyName>
+    <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <NuGetPackageImportStamp>
+    </NuGetPackageImportStamp>
+    <TargetFrameworkProfile />
+    <IsWebBootstrapper>false</IsWebBootstrapper>
+    <PublishUrl>publish\</PublishUrl>
+    <Install>true</Install>
+    <InstallFrom>Disk</InstallFrom>
+    <UpdateEnabled>false</UpdateEnabled>
+    <UpdateMode>Foreground</UpdateMode>
+    <UpdateInterval>7</UpdateInterval>
+    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+    <UpdatePeriodically>false</UpdatePeriodically>
+    <UpdateRequired>false</UpdateRequired>
+    <MapFileExtensions>true</MapFileExtensions>
+    <ApplicationRevision>0</ApplicationRevision>
+    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <UseApplicationTrust>false</UseApplicationTrust>
+    <BootstrapperEnabled>true</BootstrapperEnabled>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
+    <LangVersion>7</LangVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <LangVersion>7</LangVersion>
+    <Prefer32Bit>false</Prefer32Bit>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <PropertyGroup />
+  <PropertyGroup />
+  <PropertyGroup />
+  <PropertyGroup>
+    <ApplicationManifest>app.manifest</ApplicationManifest>
+  </PropertyGroup>
+  <PropertyGroup>
+    <ApplicationIcon>256.ico</ApplicationIcon>
+  </PropertyGroup>
+  <PropertyGroup>
+    <StartupObject />
+  </PropertyGroup>
+  <PropertyGroup>
+    <SignAssembly>false</SignAssembly>
+  </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyOriginatorKeyFile>
+    </AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <PropertyGroup>
+    <SignManifests>false</SignManifests>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="Api\Network\Messages\MessageResolver.cs" />
+    <Compile Include="Api\Network\Messages\PacketLoader.cs" />
+    <Compile Include="Api\Network\Messages\RectangleConverter.cs" />
+    <Compile Include="Api\Network\Models\FanInformation.cs" />
+    <Compile Include="Api\Network\Models\LoginInformation.cs" />
+    <Compile Include="Api\Network\PacketHandlers\DisplayPacketHandler.cs" />
+    <Compile Include="Api\Services\LocalSystem\Daemons\JobModel.cs" />
+    <Compile Include="Api\Network\PacketHandlers\CronJobPacketHandler.cs" />
+    <Compile Include="Api\Services\LocalSystem\Daemons\CronDaemon.cs" />
+    <Compile Include="Api\Services\LocalSystem\Daemons\CronJob.cs" />
+    <Compile Include="Api\Services\LocalSystem\Daemons\CronSchedule.cs" />
+    <Compile Include="Api\Services\LocalSystem\CronJobService.cs" />
+    <Compile Include="Api\Services\Update\UpdateService.cs" />
+    <Compile Include="Api\Network\Messages\Message.cs" />
+    <Compile Include="Api\Network\Messages\MessageQueueManager.cs" />
+    <Compile Include="Api\Services\LocalSystem\FileSearchService.cs" />
+    <Compile Include="Api\SystemData.cs" />
+    <Compile Include="Api\Win32\Desktop.cs" />
+    <Compile Include="Api\Win32\DesktopWatcher.cs" />
+    <Compile Include="Api\Win32\Display.cs" />
+    <Compile Include="Api\Win32\ScreenShare\DesktopDuplication\DesktopDuplicationException.cs" />
+    <Compile Include="Api\Win32\ScreenShare\DesktopDuplication\DesktopDuplicator.cs" />
+    <Compile Include="Api\Win32\ScreenShare\DesktopDuplication\DesktopFrame.cs" />
+    <Compile Include="Api\Win32\ScreenShare\DesktopDuplication\FinishedRegions.cs" />
+    <Compile Include="Api\Win32\ScreenShare\DesktopDuplication\MovedRegion.cs" />
+    <Compile Include="Api\Win32\ScreenShare\Models\DisplayInformation.cs" />
+    <Compile Include="Api\Win32\ScreenShare\Models\FrameInformation.cs" />
+    <Compile Include="Api\Win32\ScreenShare\Models\ResolutionInformation.cs" />
+    <Compile Include="Api\Win32\ScreenShare\ScreenData.cs" />
+    <Compile Include="Api\Win32\SessionInfo.cs" />
+    <Compile Include="Api\Win32\Win32Exception.cs" />
+    <Compile Include="Api\Win32\WinApi.cs" />
+    <Compile Include="Api\Win32\WindowsIdentityImpersonator.cs" />
+    <Compile Include="Forms\Utilities\AboutBox.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Forms\Utilities\AboutBox.Designer.cs">
+      <DependentUpon>AboutBox.cs</DependentUpon>
+    </Compile>
+    <Compile Include="TerminalServer\Infrastructure\ILogger.cs" />
+    <Compile Include="TerminalServer\Infrastructure\Log4NetLogger.cs" />
+    <Compile Include="Ulterius.cs" />
+    <Compile Include="Utilities\AppEnvironment.cs" />
+    <Compile Include="Utilities\Config.cs" />
+    <Compile Include="Utilities\Drive\PartitionModel.cs" />
+    <Compile Include="Utilities\Drive\SmartData.cs" />
+    <Compile Include="Utilities\Drive\SmartEnums.cs" />
+    <Compile Include="Utilities\Drive\SmartModel.cs" />
+    <Compile Include="Utilities\Extensions\NetworkBrowser.cs" />
+    <Compile Include="Utilities\Extensions\ProcessExtensions.cs" />
+    <Compile Include="Utilities\Extensions\TaskExtensions.cs" />
+    <Compile Include="Utilities\Files\Database\DatabaseController.cs" />
+    <Compile Include="Utilities\Files\Database\DatabaseManager.cs" />
+    <Compile Include="Utilities\Security\Streams\OfbStream.cs" />
+    <Compile Include="Utilities\Security\Streams\ZeroStream.cs" />
+    <Compile Include="Utilities\Security\AuthUtils.cs" />
+    <Compile Include="WebCams\WebCamManager.cs" />
+    <Compile Include="WebSocketAPI\Authentication\AuthClient.cs" />
+    <Compile Include="Forms\Utilities\UlteriusTray.cs" />
+    <Compile Include="Api\Network\Messages\Packet.cs" />
+    <Compile Include="Api\Network\Messages\MessageBuilder.cs" />
+    <Compile Include="Api\Network\PacketHandler.cs" />
+    <Compile Include="Api\Network\PacketHandlers\ErrorPacketHandler.cs" />
+    <Compile Include="Api\Network\PacketManager.cs" />
+    <Compile Include="Api\Network\PacketHandlers\WebCamPacketHandler.cs" />
+    <Compile Include="Api\Network\PacketHandlers\FilePacketHandler.cs" />
+    <Compile Include="Api\Network\PacketHandlers\GpuPacketHandler.cs" />
+    <Compile Include="Api\Network\PacketHandlers\ScreenSharePacketHandler.cs" />
+    <Compile Include="Api\Network\PacketHandlers\AccountPacketHandler.cs" />
+    <Compile Include="Api\Network\PacketHandlers\SettingsPacketHandler.cs" />
+    <Compile Include="Api\Network\PacketHandlers\NetworkPacketHandler.cs" />
+    <Compile Include="Api\Network\PacketHandlers\CpuPacketHandler.cs" />
+    <Compile Include="Api\Network\PacketHandlers\OperatingSystemPacketHandler.cs" />
+    <Compile Include="Api\Network\PacketHandlers\ProcessPacketHandler.cs" />
+    <Compile Include="Api\Network\PacketHandlers\ServerPacketHandler.cs" />
+    <Compile Include="Api\Network\PacketHandlers\SystemPacketHandler.cs" />
+    <Compile Include="Api\Network\Models\GpuInformation.cs" />
+    <Compile Include="Api\Services\LocalSystem\ScreenShareService.cs" />
+    <Compile Include="TerminalServer\Cli\CommandSession.cs" />
+    <Compile Include="TerminalServer\Cli\PowerShellSession.cs" />
+    <Compile Include="TerminalServer\Cli\_ICliSession.cs" />
+    <Compile Include="TerminalServer\Cli\_ICliSessionFactory.cs" />
+    <Compile Include="TerminalServer\Infrastructure\SystemInfo.cs" />
+    <Compile Include="TerminalServer\Infrastructure\_ISystemInfo.cs" />
+    <Compile Include="TerminalServer\Messaging\Connection\ConnectionConnectRequest.cs" />
+    <Compile Include="TerminalServer\Messaging\Connection\IConnectionEvent.cs" />
+    <Compile Include="TerminalServer\Messaging\Connection\IConnectionRequest.cs" />
+    <Compile Include="TerminalServer\Messaging\IMessageBus.cs" />
+    <Compile Include="TerminalServer\Messaging\Serialization\DefaultEventSerializator.cs" />
+    <Compile Include="TerminalServer\Messaging\Serialization\IEventSerializator.cs" />
+    <Compile Include="TerminalServer\Messaging\TerminalControl\Events\ClosedTerminalEvent.cs" />
+    <Compile Include="TerminalServer\Messaging\TerminalControl\Events\CreatedTerminalEvent.cs" />
+    <Compile Include="TerminalServer\Messaging\TerminalControl\Events\SessionStateEvent.cs" />
+    <Compile Include="TerminalServer\Messaging\TerminalControl\Events\TerminalOutputEvent.cs" />
+    <Compile Include="TerminalServer\Messaging\TerminalControl\Events\_ITerminalEvent.cs" />
+    <Compile Include="TerminalServer\Messaging\TerminalControl\Handlers\AesHandshakeRequestHandler.cs" />
+    <Compile Include="TerminalServer\Messaging\TerminalControl\Handlers\CloseTerminalRequestHandler.cs" />
+    <Compile Include="TerminalServer\Messaging\TerminalControl\Handlers\CreateTerminalRequestHandler.cs" />
+    <Compile Include="TerminalServer\Messaging\TerminalControl\Handlers\InputTerminalRequestHandler.cs" />
+    <Compile Include="TerminalServer\Messaging\TerminalControl\Handlers\_IRequestHandler.cs" />
+    <Compile Include="TerminalServer\Messaging\TerminalControl\Requests\AesHandshakeRequest.cs" />
+    <Compile Include="TerminalServer\Messaging\TerminalControl\Requests\CloseTerminalRequest.cs" />
+    <Compile Include="TerminalServer\Messaging\TerminalControl\Requests\CreateTerminalRequest.cs" />
+    <Compile Include="TerminalServer\Messaging\TerminalControl\Requests\TerminalInputRequest.cs" />
+    <Compile Include="TerminalServer\Messaging\TerminalControl\Requests\_TerminalControlRequest.cs" />
+    <Compile Include="TerminalServer\Messaging\WebSocketHandler.cs" />
+    <Compile Include="TerminalServer\Messaging\WebSocketQueueServer.cs" />
+    <Compile Include="TerminalServer\Session\ConnectionManager.cs" />
+    <Compile Include="TerminalServer\Session\UserConnection.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Api\UlteriusApiServer.cs" />
+    <Compile Include="TerminalServer\TerminalManagerServer.cs" />
+    <Compile Include="Utilities\DynamicMap.cs" />
+    <Compile Include="Utilities\Extensions\StringExtensions.cs" />
+    <Compile Include="Utilities\Files\FileManager.cs" />
+    <Compile Include="Utilities\IconTools.cs" />
+    <Compile Include="Utilities\Security\UlteriusAes.cs" />
+    <Compile Include="Utilities\Security\Rsa.cs" />
+    <Compile Include="Utilities\Files\FileTree.cs" />
+    <Compile Include="Utilities\Trace.cs" />
+    <Compile Include="WebServer\MultipartParser.cs" />
+    <Compile Include="WebSocketAPI\Authentication\CookieManager.cs" />
+    <Compile Include="WebSocketAPI\WebSocketEventListener.cs" />
+    <Compile Include="Api\Network\Models\DriveInformation.cs" />
+    <Compile Include="Api\Network\Models\SystemInformation.cs" />
+    <Compile Include="Api\Network\Models\NetworkInformation.cs" />
+    <Compile Include="Api\Network\Models\CpuInformation.cs" />
+    <Compile Include="Api\Network\Models\OperatingSystemInformation.cs" />
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>Resources.resx</DependentUpon>
+    </Compile>
+    <Compile Include="Api\Network\Models\ProcessInformation.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Utilities\ExceptionHandler.cs" />
+    <Compile Include="Api\Services\Network\NetworkService.cs" />
+    <Compile Include="Api\Services\LocalSystem\SystemService.cs" />
+    <Compile Include="Utilities\Tools.cs" />
+    <Compile Include="WebServer\HttpServer.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="App.config" />
+    <None Include="app.manifest" />
+    <None Include="App1.config" />
+    <None Include="packages.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Forms\Utilities\AboutBox.resx">
+      <DependentUpon>AboutBox.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
+  </ItemGroup>
+  <ItemGroup>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="256.ico" />
+    <EmbeddedResource Include="Packets.json" />
+    <None Include="Resources\ApplicationIcon.ico" />
+    <Content Include="twitter-profile.ico" />
+  </ItemGroup>
+  <ItemGroup>
+    <WCFMetadata Include="Service References\" />
+  </ItemGroup>
+  <ItemGroup>
+    <Folder Include="bin\Debug\" />
+    <Folder Include="Utilities\Files\Models\" />
+  </ItemGroup>
+  <ItemGroup>
+    <Reference Include="AForge, Version=2.2.5.0, Culture=neutral, PublicKeyToken=c1db6ff4eaa06aeb, processorArchitecture=MSIL">
+      <HintPath>..\packages\AForge.2.2.5\lib\AForge.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="AForge.Imaging, Version=2.2.5.0, Culture=neutral, PublicKeyToken=ba8ddea9676ca48b, processorArchitecture=MSIL">
+      <HintPath>..\packages\AForge.Imaging.2.2.5\lib\AForge.Imaging.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="AForge.Math, Version=2.2.5.0, Culture=neutral, PublicKeyToken=abba2e25397ee8c9, processorArchitecture=MSIL">
+      <HintPath>..\packages\AForge.Math.2.2.5\lib\AForge.Math.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="AForge.Video, Version=2.2.5.0, Culture=neutral, PublicKeyToken=cbfb6e07d173c401, processorArchitecture=MSIL">
+      <HintPath>..\packages\AForge.Video.2.2.5\lib\AForge.Video.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="AForge.Video.DirectShow, Version=2.2.5.0, Culture=neutral, PublicKeyToken=61ea4348d43881b7, processorArchitecture=MSIL">
+      <HintPath>..\packages\AForge.Video.DirectShow.2.2.5\lib\AForge.Video.DirectShow.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="AForge.Vision, Version=2.2.5.0, Culture=neutral, PublicKeyToken=b612fa915eefaa06, processorArchitecture=MSIL">
+      <HintPath>..\packages\AForge.Vision.2.2.5\lib\AForge.Vision.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="BouncyCastle.Crypto, Version=1.8.1.0, Culture=neutral, PublicKeyToken=0e99375e54769942">
+      <HintPath>..\packages\BouncyCastle.1.8.1\lib\BouncyCastle.Crypto.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="deniszykov.WebSocketListener, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7f78616efb4a208d, processorArchitecture=MSIL">
+      <HintPath>..\packages\deniszykov.WebSocketListener.4.0.0\lib\net45\deniszykov.WebSocketListener.dll</HintPath>
+    </Reference>
+    <Reference Include="DotNetZip, Version=1.10.1.0, Culture=neutral, PublicKeyToken=6583c7c814667745, processorArchitecture=MSIL">
+      <HintPath>..\packages\DotNetZip.1.10.1\lib\net20\DotNetZip.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
+      <HintPath>..\packages\log4net.2.0.8\lib\net45-full\log4net.dll</HintPath>
+    </Reference>
+    <Reference Include="Magnum, Version=2.1.3.0, Culture=neutral, PublicKeyToken=b800c4cfcdeea87b, processorArchitecture=MSIL">
+      <HintPath>..\packages\Magnum.2.1.3\lib\NET40\Magnum.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="MassTransit, Version=2.9.0.0, Culture=neutral, PublicKeyToken=b8e0e9f2f1e657fa, processorArchitecture=MSIL">
+      <HintPath>..\packages\MassTransit.2.9.0\lib\net40\MassTransit.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.3\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="MiscUtil, Version=0.2.0.0, Culture=neutral, PublicKeyToken=d3c42c4bfacf7596, processorArchitecture=MSIL">
+      <HintPath>..\packages\JonSkeet.MiscUtil.0.2.0\lib\net35\MiscUtil.dll</HintPath>
+    </Reference>
+    <Reference Include="Mono.Cecil, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
+      <HintPath>..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="Mono.Cecil.Mdb, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
+      <HintPath>..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Mdb.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="Mono.Cecil.Pdb, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
+      <HintPath>..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Pdb.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="Mono.Cecil.Rocks, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
+      <HintPath>..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Rocks.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
+      <HintPath>..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
+    </Reference>
+    <Reference Include="Open.Nat, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f22a6a4582336c76, processorArchitecture=MSIL">
+      <HintPath>..\packages\Open.NAT.2.1.0.0\lib\net45\Open.Nat.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="OpenHardwareMonitorLib">
+      <HintPath>..\Deps\OpenHardwareMonitorLib.dll</HintPath>
+    </Reference>
+    <Reference Include="PresentationCore" />
+    <Reference Include="SharpDX, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
+      <HintPath>..\packages\SharpDX.4.0.1\lib\net45\SharpDX.dll</HintPath>
+    </Reference>
+    <Reference Include="SharpDX.Direct3D11, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
+      <HintPath>..\packages\SharpDX.Direct3D11.4.0.1\lib\net45\SharpDX.Direct3D11.dll</HintPath>
+    </Reference>
+    <Reference Include="SharpDX.DXGI, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
+      <HintPath>..\packages\SharpDX.DXGI.4.0.1\lib\net45\SharpDX.DXGI.dll</HintPath>
+    </Reference>
+    <Reference Include="SharpDX.Mathematics, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
+      <HintPath>..\packages\SharpDX.Mathematics.4.0.1\lib\net45\SharpDX.Mathematics.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.DirectoryServices" />
+    <Reference Include="System.DirectoryServices.AccountManagement" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.IO.Compression" />
+    <Reference Include="System.Management" />
+    <Reference Include="System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\3.0\System.Management.Automation.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Net" />
+    <Reference Include="System.Net.Http" />
+    <Reference Include="System.ServiceModel" />
+    <Reference Include="System.ServiceProcess" />
+    <Reference Include="System.Threading.Tasks.Dataflow, Version=4.6.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Threading.Tasks.Dataflow.4.8.0\lib\netstandard2.0\System.Threading.Tasks.Dataflow.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Web" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xaml" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Xml" />
+    <Reference Include="Topshelf, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b800c4cfcdeea87b, processorArchitecture=MSIL">
+      <HintPath>..\packages\Topshelf.4.0.3\lib\net452\Topshelf.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="TurboJpegWrapper, Version=1.4.2.19498, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\TurboJpegWrapper.1.4.2.6\lib\net35\TurboJpegWrapper.dll</HintPath>
+    </Reference>
+    <Reference Include="WindowsBase" />
+    <Reference Include="ZetaLongPaths, Version=1.0.0.19, Culture=neutral, PublicKeyToken=b764f59068f31f38, processorArchitecture=MSIL">
+      <HintPath>..\packages\ZetaLongPaths.1.0.0.19\lib\net40-full\ZetaLongPaths.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <COMReference Include="NetFwTypeLib">
+      <Guid>{58FBCF7C-E7A9-467C-80B3-FC65E8FCCA08}</Guid>
+      <VersionMajor>1</VersionMajor>
+      <VersionMinor>0</VersionMinor>
+      <Lcid>0</Lcid>
+      <WrapperTool>tlbimp</WrapperTool>
+      <Isolated>False</Isolated>
+      <EmbedInteropTypes>True</EmbedInteropTypes>
+    </COMReference>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\inputsimulator2\WindowsInput\WindowsInput.csproj">
+      <Project>{3549cd6f-80f8-450f-b99e-cf0a736b1f2a}</Project>
+      <Name>WindowsInput</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\UlteriusAgent\UlteriusAgent.csproj">
+      <Project>{686ae4c4-791f-45eb-9414-029d6115905d}</Project>
+      <Name>UlteriusAgent</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.3\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.3\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props'))" />
+    <Error Condition="!Exists('..\packages\TurboJpegWrapper.1.4.2.6\build\TurboJpegWrapper.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\TurboJpegWrapper.1.4.2.6\build\TurboJpegWrapper.targets'))" />
+    <Error Condition="!Exists('..\packages\Microsoft.Net.Compilers.2.4.0\build\Microsoft.Net.Compilers.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Net.Compilers.2.4.0\build\Microsoft.Net.Compilers.props'))" />
+  </Target>
+  <PropertyGroup>
+    <PostBuildEvent>
+    </PostBuildEvent>
+  </PropertyGroup>
+  <PropertyGroup>
+    <PreBuildEvent>
+    </PreBuildEvent>
+  </PropertyGroup>
+  <Target Name="AfterClean">
+    <Delete Files="$(TargetDir)\*.dll" />
+  </Target>
+  <Target Name="AfterClean">
+    <ItemGroup>
+      <FilesToDelete Include="$(TargetDir)\*.dll" />
+    </ItemGroup>
+    <Delete Files="@(FilesToDelete)" />
+  </Target>
 </Project>
\ No newline at end of file
diff --git a/RemoteTaskServer/UlteriusServer.csproj.DotSettings b/RemoteTaskServer/UlteriusServer.csproj.DotSettings
new file mode 100644
index 0000000..c54c126
--- /dev/null
+++ b/RemoteTaskServer/UlteriusServer.csproj.DotSettings
@@ -0,0 +1,2 @@
+﻿<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
+	<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp70</s:String></wpf:ResourceDictionary>
\ No newline at end of file
diff --git a/AgentInterface/Settings/AppEnvironment.cs b/RemoteTaskServer/Utilities/AppEnvironment.cs
similarity index 99%
rename from AgentInterface/Settings/AppEnvironment.cs
rename to RemoteTaskServer/Utilities/AppEnvironment.cs
index e80d3ff..95f4f28 100644
--- a/AgentInterface/Settings/AppEnvironment.cs
+++ b/RemoteTaskServer/Utilities/AppEnvironment.cs
@@ -4,11 +4,11 @@ using System;
 using System.Windows.Forms;
 using Microsoft.Win32;
 
 #endregion
 
-namespace AgentInterface.Settings
+namespace UlteriusServer.Utilities
 {
     public class AppEnvironment
     {
         public static string DataPath
         {
diff --git a/AgentInterface/Settings/Config.cs b/RemoteTaskServer/Utilities/Config.cs
similarity index 99%
rename from AgentInterface/Settings/Config.cs
rename to RemoteTaskServer/Utilities/Config.cs
index 1b44834..28dc8e0 100644
--- a/AgentInterface/Settings/Config.cs
+++ b/RemoteTaskServer/Utilities/Config.cs
@@ -4,11 +4,11 @@ using System.Collections.Generic;
 using System.IO;
 using Newtonsoft.Json;
 
 #endregion
 
-namespace AgentInterface.Settings
+namespace UlteriusServer.Utilities
 {
     public class Config
     {
         public static bool Empty;
 
diff --git a/RemoteTaskServer/Utilities/ExceptionHandler.cs b/RemoteTaskServer/Utilities/ExceptionHandler.cs
index d52406d..d511464 100644
--- a/RemoteTaskServer/Utilities/ExceptionHandler.cs
+++ b/RemoteTaskServer/Utilities/ExceptionHandler.cs
@@ -6,11 +6,10 @@ using System.Runtime.ExceptionServices;
 using System.Runtime.InteropServices;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Windows.Forms;
 using System.Windows.Threading;
-using AgentInterface.Settings;
 using Newtonsoft.Json;
 
 #endregion
 
 namespace UlteriusServer.Utilities
diff --git a/RemoteTaskServer/Utilities/Extensions/ProcessExtensions.cs b/RemoteTaskServer/Utilities/Extensions/ProcessExtensions.cs
new file mode 100644
index 0000000..7e596d1
--- /dev/null
+++ b/RemoteTaskServer/Utilities/Extensions/ProcessExtensions.cs
@@ -0,0 +1,209 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Management;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace UlteriusServer.Utilities.Extensions
+{
+    public static class ProcessExtensions
+    {
+        [DllImport("user32.dll")]
+        public static extern IntPtr FindWindowEx(IntPtr parentWindow, IntPtr previousChildWindow, string windowClass,
+            string windowTitle);
+
+        [DllImport("user32.dll")]
+        private static extern IntPtr GetWindowThreadProcessId(IntPtr window, out int process);
+
+        public static IntPtr[] GetProcessWindows(this Process process)
+        {
+            var apRet = new IntPtr[256];
+            var iCount = 0;
+            var pLast = IntPtr.Zero;
+            do
+            {
+                pLast = FindWindowEx(IntPtr.Zero, pLast, null, null);
+                int iProcess_;
+                GetWindowThreadProcessId(pLast, out iProcess_);
+                if (iProcess_ == process.Id)
+                {
+                    apRet[iCount++] = pLast;
+                }
+            } while (pLast != IntPtr.Zero);
+            Array.Resize(ref apRet, iCount);
+            return apRet;
+        }
+
+        private static string FindIndexedProcessName(int pid)
+        {
+            try
+            {
+                var processName = Process.GetProcessById(pid).ProcessName;
+                var processesByName = Process.GetProcessesByName(processName);
+                string processIndexdName = null;
+                for (var index = 0; index < processesByName.Length; index++)
+                {
+                    processIndexdName = index == 0 ? processName : processName + "#" + index;
+                    var processId = new PerformanceCounter("Process", "ID Process", processIndexdName);
+                    if ((int)processId.NextValue() == pid)
+                    {
+                        return processIndexdName;
+                    }
+                }
+                return processIndexdName;
+            }
+            catch (Exception)
+            {
+                return null;
+            }
+        }
+
+        public static List<Process> GetChildrenById(int id)
+        {
+            try
+            {
+                var mos = new ManagementObjectSearcher(
+                    $"Select * From Win32_Process Where ParentProcessID={id}");
+                return (from ManagementObject mo in mos.Get()
+                    select Process.GetProcessById(Convert.ToInt32(mo["ProcessID"]))).ToList();
+            }
+            catch (Exception)
+            {
+                return null;
+            }
+        }
+
+        public static List<Process> GetChildProcesses(this Process process)
+        {
+            try
+            {
+                var mos = new ManagementObjectSearcher(
+                    $"Select * From Win32_Process Where ParentProcessID={process.Id}");
+                return (from ManagementObject mo in mos.Get()
+                    select Process.GetProcessById(Convert.ToInt32(mo["ProcessID"]))).ToList();
+            }
+            catch (Exception)
+            {
+                return null;
+            }
+        }
+
+        public static bool IsService(this Process process)
+        {
+            if (process == null)
+            {
+                return false;
+            }
+            using (var searcher =
+                new ManagementObjectSearcher("SELECT * FROM Win32_Service WHERE ProcessId =" + "\"" + process.Id +
+                                             "\""))
+            {
+                if (searcher.Get().Cast<ManagementObject>().Any())
+                {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        [DllImport("kernel32.dll")]
+        public static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId);
+
+        [DllImport("psapi.dll")]
+        private static extern uint GetModuleFileNameEx(IntPtr hProcess, IntPtr hModule, [Out] StringBuilder lpBaseName,
+            [In] [MarshalAs(UnmanagedType.U4)] int nSize);
+
+        [DllImport("kernel32.dll", SetLastError = true)]
+        [return: MarshalAs(UnmanagedType.Bool)]
+        private static extern bool CloseHandle(IntPtr hObject);
+
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static string GetProcessName(this Process proc)
+        {
+            var processHandle = OpenProcess(0x0400 | 0x0010, false, proc.Id);
+
+            if (processHandle == IntPtr.Zero)
+            {
+                return null;
+            }
+
+            const int lengthSb = 4000;
+
+            var sb = new StringBuilder(lengthSb);
+
+            string result = null;
+
+            if (GetModuleFileNameEx(processHandle, IntPtr.Zero, sb, lengthSb) > 0)
+            {
+                result = Path.GetFileName(sb.ToString());
+            }
+
+            CloseHandle(processHandle);
+
+            return result;
+        }
+
+        public static Process GetProcess(string path)
+        {
+            try
+            {
+                return Process.GetProcessesByName(Path.GetFileNameWithoutExtension(path)).FirstOrDefault();
+            }
+            catch
+            {
+
+                return null;
+            }
+        }
+
+        private static Process FindPidFromIndexedProcessName(string indexedProcessName)
+        {
+            try
+            {
+                var parentId = new PerformanceCounter("Process", "Creating Process ID", indexedProcessName);
+                return Process.GetProcessById((int)parentId.NextValue());
+            }
+            catch (Exception)
+            {
+                return null;
+            }
+        }
+
+
+        public static void KillProcessAndChildren(this Process process)
+        {
+            try
+            {
+                var searcher = new ManagementObjectSearcher("Select * From Win32_Process Where ParentProcessID=" + process.Id);
+                var moc = searcher.Get();
+                foreach (var o in moc)
+                {
+                    var mo = (ManagementObject)o;
+                    var child = Process.GetProcessById(Convert.ToInt32(mo["ProcessID"]));
+                    KillProcessAndChildren(child);
+                    child.Kill();
+                }
+                process.Kill();
+            }
+            catch
+            {
+                // Process already exited.
+            }
+        }
+
+        public static bool ProgramIsRunning(string fullPath)
+        {
+            return Process.GetProcessesByName(Path.GetFileNameWithoutExtension(fullPath)).Count() > 1;
+        }
+
+        public static Process Parent(this Process process)
+        {
+            return FindPidFromIndexedProcessName(FindIndexedProcessName(process.Id));
+        }
+    }
+}
\ No newline at end of file
diff --git a/RemoteTaskServer/Utilities/Extensions/StringExtensions.cs b/RemoteTaskServer/Utilities/Extensions/StringExtensions.cs
index 6388c7f..7f63dea 100644
--- a/RemoteTaskServer/Utilities/Extensions/StringExtensions.cs
+++ b/RemoteTaskServer/Utilities/Extensions/StringExtensions.cs
@@ -1,427 +1,505 @@
-﻿#region
-
-using System;
-using System.Collections.Generic;
-using System.Runtime.InteropServices;
-using System.Security;
-using System.Security.Cryptography;
-using System.Text;
-using System.Text.RegularExpressions;
-using System.Web.UI;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-
-#endregion
-
-namespace UlteriusServer.Utilities.Extensions
-{
-    /// <summary>
-    ///     Enum FormatTokenFlags
-    /// </summary>
-    public enum FormatTokenFlags
-    {
-        /// <summary>
-        ///     Uses the specifier token as the replacement token, matches '%' but not '%%'
-        /// </summary>
-        SpecifierToken,
-
-        /// <summary>
-        ///     Like String.Format
-        /// </summary>
-        IndexToken,
-
-        /// <summary>
-        ///     Extracts an Object's Members by name.
-        /// </summary>
-        MemberToken
-    }
-
-    /// <summary>
-    ///     Class StringExtensions
-    /// </summary>
-    public static class StringExtensions
-    {
-
-        // Returns the human-readable file totalSize for an arbitrary, 64-bit file totalSize 
-        // The default format is "0.### XB", e.g. "4.2 KB" or "1.434 GB"
-
-        public static string UnicodeUtf8(this string strFrom)
-        {
-            var bytSrc = Encoding.Unicode.GetBytes(strFrom);
-            var bytDestination = Encoding.Convert(Encoding.Unicode, Encoding.UTF8, bytSrc);
-            var strTo = Encoding.UTF8.GetString(bytDestination);
-            return strTo;
-        }
-
-        /// <summary>
-        /// Implement's VB's Like operator logic.
-        /// </summary>
-        public static bool IsLike(this string s, string pattern)
-        {
-            // Characters matched so far
-            int matched = 0;
-
-            // Loop through pattern string
-            for (int i = 0; i < pattern.Length;)
-            {
-                // Check for end of string
-                if (matched > s.Length)
-                    return false;
-
-                // Get next pattern character
-                char c = pattern[i++];
-                if (c == '[') // Character list
-                {
-                    // Test for exclude character
-                    bool exclude = (i < pattern.Length && pattern[i] == '!');
-                    if (exclude)
-                        i++;
-                    // Build character list
-                    int j = pattern.IndexOf(']', i);
-                    if (j < 0)
-                        j = s.Length;
-                    HashSet<char> charList = CharListToSet(pattern.Substring(i, j - i));
-                    i = j + 1;
-
-                    if (charList.Contains(s[matched]) == exclude)
-                        return false;
-                    matched++;
-                }
-                else if (c == '?') // Any single character
-                {
-                    matched++;
-                }
-                else if (c == '#') // Any single digit
-                {
-                    if (!Char.IsDigit(s[matched]))
-                        return false;
-                    matched++;
-                }
-                else if (c == '*') // Zero or more characters
-                {
-                    if (i < pattern.Length)
-                    {
-                        // Matches all characters until
-                        // next character in pattern
-                        char next = pattern[i];
-                        int j = s.IndexOf(next, matched);
-                        if (j < 0)
-                            return false;
-                        matched = j;
-                    }
-                    else
-                    {
-                        // Matches all remaining characters
-                        matched = s.Length;
-                        break;
-                    }
-                }
-                else // Exact character
-                {
-                    if (matched >= s.Length || c != s[matched])
-                        return false;
-                    matched++;
-                }
-            }
-            // Return true if all characters matched
-            return (matched == s.Length);
-        }
-
-        /// <summary>
-        /// Converts a string of characters to a HashSet of characters. If the string
-        /// contains character ranges, such as A-Z, all characters in the range are
-        /// also added to the returned set of characters.
-        /// </summary>
-        /// <param name="charList">Character list string</param>
-        private static HashSet<char> CharListToSet(string charList)
-        {
-            HashSet<char> set = new HashSet<char>();
-
-            for (int i = 0; i < charList.Length; i++)
-            {
-                if ((i + 1) < charList.Length && charList[i + 1] == '-')
-                {
-                    // Character range
-                    char startChar = charList[i++];
-                    i++; // Hyphen
-                    char endChar = (char)0;
-                    if (i < charList.Length)
-                        endChar = charList[i++];
-                    for (int j = startChar; j <= endChar; j++)
-                        set.Add((char)j);
-                }
-                else set.Add(charList[i]);
-            }
-            return set;
-        }
-
-        public static string GetBytesReadable(long i)
-        {
-            // Get absolute value
-            var absoluteI = i < 0 ? -i : i;
-            // Determine the suffix and readable value
-            string suffix;
-            double readable;
-            if (absoluteI >= 0x1000000000000000) // Exabyte
-            {
-                suffix = "EB";
-                readable = i >> 50;
-            }
-            else if (absoluteI >= 0x4000000000000) // Petabyte
-            {
-                suffix = "PB";
-                readable = i >> 40;
-            }
-            else if (absoluteI >= 0x10000000000) // Terabyte
-            {
-                suffix = "TB";
-                readable = i >> 30;
-            }
-            else if (absoluteI >= 0x40000000) // Gigabyte
-            {
-                suffix = "GB";
-                readable = i >> 20;
-            }
-            else if (absoluteI >= 0x100000) // Megabyte
-            {
-                suffix = "MB";
-                readable = i >> 10;
-            }
-            else if (absoluteI >= 0x400) // Kilobyte
-            {
-                suffix = "KB";
-                readable = i;
-            }
-            else
-            {
-                return i.ToString("0 B"); // Byte
-            }
-            // Divide by 1024 to get fractional value
-            readable = readable / 1024;
-            // Return formatted number with suffix
-            return readable.ToString("0.### ") + suffix;
-        }
-
-        /// <summary>
-        /// Returns a Secure string from the source string
-        /// </summary>
-        /// <param name="Source"></param>
-        /// <returns></returns>
-        public static SecureString ToSecureString(this string Source)
-        {
-            if (string.IsNullOrWhiteSpace(Source))
-                return null;
-            var Result = new SecureString();
-            foreach (var c in Source.ToCharArray())
-                Result.AppendChar(c);
-            return Result;
-        }
-        public static string ToUnsecureString(this SecureString secureString)
-        {
-            if (secureString == null) throw new ArgumentNullException("secureString");
-
-            var unmanagedString = IntPtr.Zero;
-            try
-            {
-                unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(secureString);
-                return Marshal.PtrToStringUni(unmanagedString);
-            }
-            finally
-            {
-                Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString);
-            }
-        }
-
-
-        /// <summary>
-        ///     The Reformatting function called to format the string with a list of arguments.
-        /// </summary>
-        private static Func<Func<string, object>, string, IList<object>, string> _regexReformatter;
-
-        /// <summary>
-        ///     The Regex which matches the specifier token in strings.
-        /// </summary>
-        private static Regex _specifierTokenRegex;
-
-        /// <summary>
-        ///     The Regex which matches parameter indexes in strings, same as string.Format.
-        /// </summary>
-        private static Regex _argumentIndexRegex;
-
-        /// <summary>
-        ///     The Regex which matches object member names in strings.
-        /// </summary>
-        private static Regex _objectMemberRegex;
-
-        /// <summary>
-        ///     Splits a string into an array of strings, the string is split by commas.
-        /// </summary>
-        /// <param name="this">The string instance to split by commas.</param>
-        /// <returns>The <paramref name="this" /> string that has been comma separated into substrings.</returns>
-        public static string[] CommaSeparate(this string @this)
-        {
-            return @this.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
-        }
-
-        /// <summary>
-        ///     Determines whether two String objects contain the same data, ignoring the case of the letters in the String; uses
-        ///     Ordinal comparison.
-        /// </summary>
-        /// <param name="this">The current string to be compared to.</param>
-        /// <param name="other">The other string to compare against the current String for equality.</param>
-        /// <returns><c>true</c> if the two strings are equal, <c>false</c> otherwise</returns>
-        public static bool EqualsIgnoreCase(this string @this, string other)
-        {
-            return string.Equals(@this, other, StringComparison.OrdinalIgnoreCase);
-        }
-
-        public static bool IsBase64String(this string s)
-        {
-            s = s.Trim();
-            return (s.Length%4 == 0) && Regex.IsMatch(s, @"^[a-zA-Z0-9\+/]*={0,3}$", RegexOptions.None);
-        }
-
-        public static bool IsValidJson(this string strInput)
-        {
-            strInput = strInput.Trim();
-            if ((strInput.StartsWith("{") && strInput.EndsWith("}")) || //For object
-                (strInput.StartsWith("[") && strInput.EndsWith("]"))) //For array
-            {
-                try
-                {
-                    JToken.Parse(strInput);
-                    return true;
-                }
-                catch (JsonReaderException)
-                {
-                    //Exception in parsing json
-                    return false;
-                }
-                catch (Exception) //some other exception
-                {
-                    return false;
-                }
-            }
-            return false;
-        }
-
-
-        /// <summary>
-        ///     Replaces one or more format items in a specified string with the string representation of a specified object.
-        /// </summary>
-        /// <returns>
-        ///     A copy of <paramref name="format" /> in which any format items are replaced by the string representation of
-        ///     <paramref name="values" />.
-        /// </returns>
-        /// <param name="format">A composite format string. </param>
-        /// <param name="values">The arguments to use in formatting <paramref name="format" />.</param>
-        public static string Form(this string format, params object[] values)
-        {
-            var specifierTokenMatches = _specifierTokenRegex.Matches(format);
-            var indexTokenMatches = _argumentIndexRegex.Matches(format);
-            var memberNameMatches = _objectMemberRegex.Matches(format);
-
-            if (memberNameMatches.Count > 0 && values.Length == 1)
-            {
-                format = FormatString(format, FormatTokenFlags.MemberToken, values);
-            }
-            else
-            {
-                if (indexTokenMatches.Count > 0)
-                {
-                    format = FormatString(format, FormatTokenFlags.IndexToken, values);
-                }
-
-                if (specifierTokenMatches.Count > 0)
-                {
-                    format = FormatString(format, FormatTokenFlags.SpecifierToken, values);
-                }
-            }
-            return format;
-        }
-
-        public static string CreateMD5(this string input)
-        {
-            // Use input string to calculate MD5 hash
-            using (var md5 = MD5.Create())
-            {
-                var inputBytes = Encoding.ASCII.GetBytes(input);
-                var hashBytes = md5.ComputeHash(inputBytes);
-
-                // Convert the byte array to hexadecimal string
-                var sb = new StringBuilder();
-                foreach (var t in hashBytes)
-                {
-                    sb.Append(t.ToString("X2"));
-                }
-                return sb.ToString();
-            }
-        }
-
-        /// <summary>
-        ///     The Function which does all the heavy lifting.
-        /// </summary>
-        /// <param name="format">A composite format string</param>
-        /// <param name="flags">The flags which specify how the <paramref name="format" /> string should be interpreted.</param>
-        /// <param name="arguments">The arguments to format the <paramref name="format" /> parameter with.</param>
-        /// <returns>System.String.</returns>
-        public static string FormatString(string format, FormatTokenFlags flags, params object[] arguments)
-        {
-            switch (flags)
-            {
-                case FormatTokenFlags.IndexToken:
-                    return string.Format(format, arguments);
-
-                case FormatTokenFlags.SpecifierToken:
-                    var stringBuilder = new StringBuilder();
-                    for (int i = 0,
-                        argIndex = 0;
-                        i < format.Length;
-                        i++)
-                    {
-                        stringBuilder.Append(format[i] == '%' && argIndex < arguments.Length
-                            ? "{" + argIndex++ + "}"
-                            : format.Substring(i, 1));
-                    }
-                    return string.Format(stringBuilder.ToString(), arguments);
-
-                case FormatTokenFlags.MemberToken:
-                    return
-                        string.Format(
-                            _regexReformatter(name => name == "0" ? arguments[0] : DataBinder.Eval(arguments[0], name),
-                                format, arguments), arguments);
-
-                default:
-                    return format;
-            }
-        }
-
-        public static void Initialize()
-        {
-            const RegexOptions regexOptions = RegexOptions.Compiled | RegexOptions.CultureInvariant;
-            _objectMemberRegex = new Regex(@"(?<start>(\{))+(?<property>[\w\.]+)(?<end>(\}))+", regexOptions);
-            _specifierTokenRegex = new Regex(@"(?<!\\)%", regexOptions);
-            _argumentIndexRegex = new Regex(@"\{(\d)\}", regexOptions);
-            _regexReformatter = (valueFetcher, format, parameters) =>
-            {
-                var argumentCollection = new List<object>();
-                var rewrittenFormat = _objectMemberRegex.Replace(format, match =>
-                {
-                    Group startGroup = match.Groups["start"],
-                        propertyGroup = match.Groups["property"],
-                        endGroup = match.Groups["end"];
-
-                    var result = valueFetcher(propertyGroup.Value);
-
-                    argumentCollection.Add(result);
-                    var index = argumentCollection.Count - 1;
-                    var fmt = new string('{', startGroup.Captures.Count) + index +
-                              new string('}', endGroup.Captures.Count);
-                    return string.Format(fmt, argumentCollection.ToArray());
-                });
-
-                return rewrittenFormat;
-            };
-        }
-    }
+﻿#region
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Cryptography;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Web.UI;
+using MassTransit.Util;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+
+#endregion
+
+namespace UlteriusServer.Utilities.Extensions
+{
+    /// <summary>
+    ///     Enum FormatTokenFlags
+    /// </summary>
+    public enum FormatTokenFlags
+    {
+        /// <summary>
+        ///     Uses the specifier token as the replacement token, matches '%' but not '%%'
+        /// </summary>
+        SpecifierToken,
+
+        /// <summary>
+        ///     Like String.Format
+        /// </summary>
+        IndexToken,
+
+        /// <summary>
+        ///     Extracts an Object's Members by name.
+        /// </summary>
+        MemberToken
+    }
+
+    /// <summary>
+    ///     Class StringExtensions
+    /// </summary>
+    public static class StringExtensions
+    {
+
+        // Returns the human-readable file totalSize for an arbitrary, 64-bit file totalSize 
+        // The default format is "0.### XB", e.g. "4.2 KB" or "1.434 GB"
+
+        public static string UnicodeUtf8(this string strFrom)
+        {
+            var bytSrc = Encoding.Unicode.GetBytes(strFrom);
+            var bytDestination = Encoding.Convert(Encoding.Unicode, Encoding.UTF8, bytSrc);
+            var strTo = Encoding.UTF8.GetString(bytDestination);
+            return strTo;
+        }
+
+        /// <summary>
+        /// Implement's VB's Like operator logic.
+        /// </summary>
+        public static bool IsLike(this string s, string pattern)
+        {
+            // Characters matched so far
+            var matched = 0;
+
+            // Loop through pattern string
+            for (var i = 0; i < pattern.Length;)
+            {
+                // Check for end of string
+                if (matched > s.Length)
+                    return false;
+
+                // Get next pattern character
+                var c = pattern[i++];
+                if (c == '[') // Character list
+                {
+                    // Test for exclude character
+                    var exclude = (i < pattern.Length && pattern[i] == '!');
+                    if (exclude)
+                        i++;
+                    // Build character list
+                    var j = pattern.IndexOf(']', i);
+                    if (j < 0)
+                        j = s.Length;
+                    var charList = CharListToSet(pattern.Substring(i, j - i));
+                    i = j + 1;
+
+                    if (charList.Contains(s[matched]) == exclude)
+                        return false;
+                    matched++;
+                }
+                else if (c == '?') // Any single character
+                {
+                    matched++;
+                }
+                else if (c == '#') // Any single digit
+                {
+                    if (!Char.IsDigit(s[matched]))
+                        return false;
+                    matched++;
+                }
+                else if (c == '*') // Zero or more characters
+                {
+                    if (i < pattern.Length)
+                    {
+                        // Matches all characters until
+                        // next character in pattern
+                        var next = pattern[i];
+                        var j = s.IndexOf(next, matched);
+                        if (j < 0)
+                            return false;
+                        matched = j;
+                    }
+                    else
+                    {
+                        // Matches all remaining characters
+                        matched = s.Length;
+                        break;
+                    }
+                }
+                else // Exact character
+                {
+                    if (matched >= s.Length || c != s[matched])
+                        return false;
+                    matched++;
+                }
+            }
+            // Return true if all characters matched
+            return (matched == s.Length);
+        }
+        /// <summary>
+        /// Checks if a string is a valid email
+        /// </summary>
+        /// <param name="email"></param>
+        /// <returns></returns>
+        public static bool IsValidEmail(this string email)
+        {
+            try
+            {
+                var addr = new System.Net.Mail.MailAddress(email);
+                return addr.Address == email;
+            }
+            catch
+            {
+                return false;
+            }
+        }
+
+        /// <summary>
+        /// Returns true if <paramref name="path"/> starts with the path <paramref name="baseDirPath"/>.
+        /// The comparison is case-insensitive, handles / and \ slashes as folder separators and
+        /// only matches if the base dir folder name is matched exactly ("c:\foobar\file.txt" is not a sub path of "c:\foo").
+        /// </summary>
+        public static bool IsSubPathOf(this string path, string baseDirPath)
+        {
+            var normalizedPath = Path.GetFullPath(path.Replace('/', '\\')
+                .WithEnding("\\"));
+
+            var normalizedBaseDirPath = Path.GetFullPath(baseDirPath.Replace('/', '\\')
+                .WithEnding("\\"));
+
+            return normalizedPath.StartsWith(normalizedBaseDirPath, StringComparison.OrdinalIgnoreCase);
+        }
+
+        /// <summary>
+        /// Returns <paramref name="str"/> with the minimal concatenation of <paramref name="ending"/> (starting from end) that
+        /// results in satisfying .EndsWith(ending).
+        /// </summary>
+        /// <example>"hel".WithEnding("llo") returns "hello", which is the result of "hel" + "lo".</example>
+        public static string WithEnding([CanBeNull] this string str, string ending)
+        {
+            if (str == null)
+                return ending;
+
+            var result = str;
+
+            // Right() is 1-indexed, so include these cases
+            // * Append no characters
+            // * Append up to N characters, where N is ending length
+            for (var i = 0; i <= ending.Length; i++)
+            {
+                var tmp = result + ending.Right(i);
+                if (tmp.EndsWith(ending))
+                    return tmp;
+            }
+
+            return result;
+        }
+
+        /// <summary>Gets the rightmost <paramref name="length" /> characters from a string.</summary>
+        /// <param name="value">The string to retrieve the substring from.</param>
+        /// <param name="length">The number of characters to retrieve.</param>
+        /// <returns>The substring.</returns>
+        public static string Right([NotNull] this string value, int length)
+        {
+            if (value == null)
+            {
+                throw new ArgumentNullException("value");
+            }
+            if (length < 0)
+            {
+                throw new ArgumentOutOfRangeException("length", length, "Length is less than zero");
+            }
+
+            return (length < value.Length) ? value.Substring(value.Length - length) : value;
+        }
+
+        /// <summary>
+        /// Converts a string of characters to a HashSet of characters. If the string
+        /// contains character ranges, such as A-Z, all characters in the range are
+        /// also added to the returned set of characters.
+        /// </summary>
+        /// <param name="charList">Character list string</param>
+        private static HashSet<char> CharListToSet(string charList)
+        {
+            var set = new HashSet<char>();
+
+            for (var i = 0; i < charList.Length; i++)
+            {
+                if ((i + 1) < charList.Length && charList[i + 1] == '-')
+                {
+                    // Character range
+                    var startChar = charList[i++];
+                    i++; // Hyphen
+                    var endChar = (char)0;
+                    if (i < charList.Length)
+                        endChar = charList[i++];
+                    for (int j = startChar; j <= endChar; j++)
+                        set.Add((char)j);
+                }
+                else set.Add(charList[i]);
+            }
+            return set;
+        }
+
+        public static string GetBytesReadable(long i)
+        {
+            // Get absolute value
+            var absoluteI = i < 0 ? -i : i;
+            // Determine the suffix and readable value
+            string suffix;
+            double readable;
+            if (absoluteI >= 0x1000000000000000) // Exabyte
+            {
+                suffix = "EB";
+                readable = i >> 50;
+            }
+            else if (absoluteI >= 0x4000000000000) // Petabyte
+            {
+                suffix = "PB";
+                readable = i >> 40;
+            }
+            else if (absoluteI >= 0x10000000000) // Terabyte
+            {
+                suffix = "TB";
+                readable = i >> 30;
+            }
+            else if (absoluteI >= 0x40000000) // Gigabyte
+            {
+                suffix = "GB";
+                readable = i >> 20;
+            }
+            else if (absoluteI >= 0x100000) // Megabyte
+            {
+                suffix = "MB";
+                readable = i >> 10;
+            }
+            else if (absoluteI >= 0x400) // Kilobyte
+            {
+                suffix = "KB";
+                readable = i;
+            }
+            else
+            {
+                return i.ToString("0 B"); // Byte
+            }
+            // Divide by 1024 to get fractional value
+            readable = readable / 1024;
+            // Return formatted number with suffix
+            return readable.ToString("0.### ") + suffix;
+        }
+
+        /// <summary>
+        /// Returns a Secure string from the source string
+        /// </summary>
+        /// <param name="Source"></param>
+        /// <returns></returns>
+        public static SecureString ToSecureString(this string Source)
+        {
+            if (string.IsNullOrWhiteSpace(Source))
+                return null;
+            var Result = new SecureString();
+            foreach (var c in Source.ToCharArray())
+                Result.AppendChar(c);
+            return Result;
+        }
+        public static string ToUnsecureString(this SecureString secureString)
+        {
+            if (secureString == null) throw new ArgumentNullException("secureString");
+
+            var unmanagedString = IntPtr.Zero;
+            try
+            {
+                unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(secureString);
+                return Marshal.PtrToStringUni(unmanagedString);
+            }
+            finally
+            {
+                Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString);
+            }
+        }
+
+
+        /// <summary>
+        ///     The Reformatting function called to format the string with a list of arguments.
+        /// </summary>
+        private static Func<Func<string, object>, string, IList<object>, string> _regexReformatter;
+
+        /// <summary>
+        ///     The Regex which matches the specifier token in strings.
+        /// </summary>
+        private static Regex _specifierTokenRegex;
+
+        /// <summary>
+        ///     The Regex which matches parameter indexes in strings, same as string.Format.
+        /// </summary>
+        private static Regex _argumentIndexRegex;
+
+        /// <summary>
+        ///     The Regex which matches object member names in strings.
+        /// </summary>
+        private static Regex _objectMemberRegex;
+
+        /// <summary>
+        ///     Splits a string into an array of strings, the string is split by commas.
+        /// </summary>
+        /// <param name="this">The string instance to split by commas.</param>
+        /// <returns>The <paramref name="this" /> string that has been comma separated into substrings.</returns>
+        public static string[] CommaSeparate(this string @this)
+        {
+            return @this.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
+        }
+
+        /// <summary>
+        ///     Determines whether two String objects contain the same data, ignoring the case of the letters in the String; uses
+        ///     Ordinal comparison.
+        /// </summary>
+        /// <param name="this">The current string to be compared to.</param>
+        /// <param name="other">The other string to compare against the current String for equality.</param>
+        /// <returns><c>true</c> if the two strings are equal, <c>false</c> otherwise</returns>
+        public static bool EqualsIgnoreCase(this string @this, string other)
+        {
+            return string.Equals(@this, other, StringComparison.OrdinalIgnoreCase);
+        }
+
+        public static bool IsBase64String(this string s)
+        {
+            s = s.Trim();
+            return (s.Length%4 == 0) && Regex.IsMatch(s, @"^[a-zA-Z0-9\+/]*={0,3}$", RegexOptions.None);
+        }
+
+        public static bool IsValidJson(this string strInput)
+        {
+            strInput = strInput.Trim();
+            if ((strInput.StartsWith("{") && strInput.EndsWith("}")) || //For object
+                (strInput.StartsWith("[") && strInput.EndsWith("]"))) //For array
+            {
+                try
+                {
+                    JToken.Parse(strInput);
+                    return true;
+                }
+                catch (JsonReaderException)
+                {
+                    //Exception in parsing json
+                    return false;
+                }
+                catch (Exception) //some other exception
+                {
+                    return false;
+                }
+            }
+            return false;
+        }
+
+
+        /// <summary>
+        ///     Replaces one or more format items in a specified string with the string representation of a specified object.
+        /// </summary>
+        /// <returns>
+        ///     A copy of <paramref name="format" /> in which any format items are replaced by the string representation of
+        ///     <paramref name="values" />.
+        /// </returns>
+        /// <param name="format">A composite format string. </param>
+        /// <param name="values">The arguments to use in formatting <paramref name="format" />.</param>
+        public static string Form(this string format, params object[] values)
+        {
+            var specifierTokenMatches = _specifierTokenRegex.Matches(format);
+            var indexTokenMatches = _argumentIndexRegex.Matches(format);
+            var memberNameMatches = _objectMemberRegex.Matches(format);
+
+            if (memberNameMatches.Count > 0 && values.Length == 1)
+            {
+                format = FormatString(format, FormatTokenFlags.MemberToken, values);
+            }
+            else
+            {
+                if (indexTokenMatches.Count > 0)
+                {
+                    format = FormatString(format, FormatTokenFlags.IndexToken, values);
+                }
+
+                if (specifierTokenMatches.Count > 0)
+                {
+                    format = FormatString(format, FormatTokenFlags.SpecifierToken, values);
+                }
+            }
+            return format;
+        }
+
+        public static string CreateMD5(this string input)
+        {
+            // Use input string to calculate MD5 hash
+            using (var md5 = MD5.Create())
+            {
+                var inputBytes = Encoding.ASCII.GetBytes(input);
+                var hashBytes = md5.ComputeHash(inputBytes);
+
+                // Convert the byte array to hexadecimal string
+                var sb = new StringBuilder();
+                foreach (var t in hashBytes)
+                {
+                    sb.Append(t.ToString("X2"));
+                }
+                return sb.ToString();
+            }
+        }
+
+        /// <summary>
+        ///     The Function which does all the heavy lifting.
+        /// </summary>
+        /// <param name="format">A composite format string</param>
+        /// <param name="flags">The flags which specify how the <paramref name="format" /> string should be interpreted.</param>
+        /// <param name="arguments">The arguments to format the <paramref name="format" /> parameter with.</param>
+        /// <returns>System.String.</returns>
+        public static string FormatString(string format, FormatTokenFlags flags, params object[] arguments)
+        {
+            switch (flags)
+            {
+                case FormatTokenFlags.IndexToken:
+                    return string.Format(format, arguments);
+
+                case FormatTokenFlags.SpecifierToken:
+                    var stringBuilder = new StringBuilder();
+                    for (int i = 0,
+                        argIndex = 0;
+                        i < format.Length;
+                        i++)
+                    {
+                        stringBuilder.Append(format[i] == '%' && argIndex < arguments.Length
+                            ? "{" + argIndex++ + "}"
+                            : format.Substring(i, 1));
+                    }
+                    return string.Format(stringBuilder.ToString(), arguments);
+
+                case FormatTokenFlags.MemberToken:
+                    return
+                        string.Format(
+                            _regexReformatter(name => name == "0" ? arguments[0] : DataBinder.Eval(arguments[0], name),
+                                format, arguments), arguments);
+
+                default:
+                    return format;
+            }
+        }
+
+        public static void Initialize()
+        {
+            const RegexOptions regexOptions = RegexOptions.Compiled | RegexOptions.CultureInvariant;
+            _objectMemberRegex = new Regex(@"(?<start>(\{))+(?<property>[\w\.]+)(?<end>(\}))+", regexOptions);
+            _specifierTokenRegex = new Regex(@"(?<!\\)%", regexOptions);
+            _argumentIndexRegex = new Regex(@"\{(\d)\}", regexOptions);
+            _regexReformatter = (valueFetcher, format, parameters) =>
+            {
+                var argumentCollection = new List<object>();
+                var rewrittenFormat = _objectMemberRegex.Replace(format, match =>
+                {
+                    Group startGroup = match.Groups["start"],
+                        propertyGroup = match.Groups["property"],
+                        endGroup = match.Groups["end"];
+
+                    var result = valueFetcher(propertyGroup.Value);
+
+                    argumentCollection.Add(result);
+                    var index = argumentCollection.Count - 1;
+                    var fmt = new string('{', startGroup.Captures.Count) + index +
+                              new string('}', endGroup.Captures.Count);
+                    return string.Format(fmt, argumentCollection.ToArray());
+                });
+
+                return rewrittenFormat;
+            };
+        }
+    }
 }
\ No newline at end of file
diff --git a/RemoteTaskServer/Utilities/Security/AuthUtils.cs b/RemoteTaskServer/Utilities/Security/AuthUtils.cs
index cf2d9e3..2562058 100644
--- a/RemoteTaskServer/Utilities/Security/AuthUtils.cs
+++ b/RemoteTaskServer/Utilities/Security/AuthUtils.cs
@@ -1,12 +1,13 @@
 ﻿#region
 
 using System;
 using System.Diagnostics;
 using System.Security.Principal;
-using AgentInterface.Api.Win32;
 using UlteriusServer.Api.Network.Models;
+using UlteriusServer.Api.Win32;
+using UlteriusServer.Utilities.Extensions;
 
 #endregion
 
 namespace UlteriusServer.Utilities.Security
 {
@@ -46,18 +47,22 @@ namespace UlteriusServer.Utilities.Security
             {
 
                 return false;
             }
         }
-
+      
         public static LoginInformation AuthWindows(string username, string password)
         {
             var info = new LoginInformation();
             try
             {
                 
                 var domainName = Environment.UserDomainName;
+                if (username.IsValidEmail())
+                {
+                    domainName = "MicrosoftAccount";
+                }
                 if (username.Contains("\\"))
                 {
                     var splitName = username.Split('\\');
                     domainName = splitName[0];
                     username = splitName[1];
diff --git a/RemoteTaskServer/Utilities/Tools.cs b/RemoteTaskServer/Utilities/Tools.cs
index e6b8123..7b9c173 100644
--- a/RemoteTaskServer/Utilities/Tools.cs
+++ b/RemoteTaskServer/Utilities/Tools.cs
@@ -13,16 +13,16 @@ using System.Reflection;
 using System.Security.Principal;
 using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Web;
-using AgentInterface.Api.ScreenShare;
-using AgentInterface.Api.Win32;
-using AgentInterface.Settings;
 using Ionic.Zip;
 using NetFwTypeLib;
 using Open.Nat;
+using UlteriusServer.Api.Win32;
+using UlteriusServer.Api.Win32.ScreenShare;
+using UlteriusServer.Utilities.Extensions;
 using static System.Security.Principal.WindowsIdentity;
 using Task = System.Threading.Tasks.Task;
 
 #endregion
 
@@ -80,21 +80,18 @@ namespace UlteriusServer.Utilities
         {
 
             try
             {
                 if (Process.GetProcessesByName("DaemonManager").Length != 0) return;
-                ProcessStarter.PROCESS_INFORMATION managerInfo;
+               
                 var managerPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
                 "DaemonManager.exe");
-                ProcessStarter.StartProcessAndBypassUAC(managerPath, 
-                out managerInfo);
-                managerProcess = Process.GetProcessById((int)managerInfo.dwProcessId);
+                managerProcess = Process.Start(managerPath);
             }
             catch (Exception)
             {
-
-               
+               //
             }
         }
 
         public static void RestartAgent()
         {
@@ -109,21 +106,15 @@ namespace UlteriusServer.Utilities
             {
                 Console.WriteLine(ex.Message);
             }
          
             Thread.Sleep(3000);
-            ProcessStarter.PROCESS_INFORMATION agentInfo;
-        
-         
-            var agentPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),"UlteriusAgent.exe");
 
-            
+            var agentPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),"UlteriusAgent.exe");
 
-            ProcessStarter.StartProcessAndBypassUAC(agentPath, 
-                out agentInfo);
+            agentProcess = Process.Start(agentPath);
             
-            agentProcess = Process.GetProcessById((int)agentInfo.dwProcessId);
             if (agentProcess != null)
             {
                 Console.WriteLine("Started Monitor on " + _CurrentSession);
             }
             else
@@ -341,14 +332,11 @@ namespace UlteriusServer.Utilities
         {
             if (SetLogging())
             {
                 Console.WriteLine("Logs Ready");
             }
-            if (!RunningAsService())
-            {
-              ScreenData.SetupDuplication();  
-            }
+            ScreenData.SetupDuplication();
             if (Config.Empty)
             {
                 if (RunningPlatform() == Platform.Windows)
                 {
                     var config = Config.Load();
@@ -359,19 +347,11 @@ namespace UlteriusServer.Utilities
                     var screenSharePort = config.ScreenShareService.ScreenSharePort;
                     var prefix = $"http://*:{webServerPort}/";
                     var username = Environment.GetEnvironmentVariable("USERNAME");
                     var userdomain = Environment.GetEnvironmentVariable("USERDOMAIN");
                     var command = $@"/C netsh http add urlacl url={prefix} user={userdomain}\{username} listen=yes";
-                    if (RunningAsService())
-                    {
-                        ProcessStarter.PROCESS_INFORMATION procInfo;
-                        ProcessStarter.StartProcessAndBypassUAC("CMD.exe " + command,  out procInfo);
-                    }
-                    else
-                    {
-                        Process.Start("CMD.exe", command);
-                    }
+                    Process.Start("CMD.exe", command);
                     OpenFirewallPort(webcamPort, "Ulterius Web Cams");
                     OpenFirewallPort(webServerPort, "Ulterius Web Server");
                     OpenFirewallPort(apiPort, "Ulterius Task Server");
                     OpenFirewallPort(terminalPort, "Ulterius Terminal Server");
                     OpenFirewallPort(screenSharePort, "Ulterius ScreenShareService");
@@ -397,21 +377,21 @@ namespace UlteriusServer.Utilities
             var proc = Process.Start(
                 new ProcessStartInfo
                 {
                     FileName = "netsh",
                     Arguments =
-                        string.Format(
-                            "firewall add allowedprogram program=\"{0}\" name=\"{1}\" profile=\"ALL\"",
-                            exeFileName, displayName),
+                        $"firewall add allowedprogram program=\"{exeFileName}\" name=\"{displayName}\" profile=\"ALL\"",
                     WindowStyle = ProcessWindowStyle.Hidden
                 });
-            proc.WaitForExit();
+            proc?.WaitForExit();
         }
 
         public static bool RunningAsService()
         {
-            return GetCurrent().Name.ToLower().Contains(@"nt authority\system");
+            var me = Process.GetCurrentProcess();
+            var parent = me.Parent();
+            return parent != null && parent.IsService();
         }
 
 
         public static bool InstallClient()
         {
diff --git a/RemoteTaskServer/Utilities/Trace.cs b/RemoteTaskServer/Utilities/Trace.cs
index 9195037..f3e4a8e 100644
--- a/RemoteTaskServer/Utilities/Trace.cs
+++ b/RemoteTaskServer/Utilities/Trace.cs
@@ -1,11 +1,10 @@
 ﻿#region
 
 using System;
 using System.Collections.Generic;
 using System.IO;
-using AgentInterface.Settings;
 using UlteriusServer.Utilities.Extensions;
 
 #endregion
 
 namespace UlteriusServer.Utilities
diff --git a/RemoteTaskServer/Utilities/Usage/HardwareSurvey.cs b/RemoteTaskServer/Utilities/Usage/HardwareSurvey.cs
deleted file mode 100644
index 3f1d8de..0000000
--- a/RemoteTaskServer/Utilities/Usage/HardwareSurvey.cs
+++ /dev/null
@@ -1,151 +0,0 @@
-﻿#region
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Management;
-using System.Net.Http;
-using System.Reflection;
-using System.Windows.Forms;
-using Microsoft.Win32;
-using Newtonsoft.Json;
-using UlteriusServer.Api.Network.Models;
-using UlteriusServer.Properties;
-using SystemInformation = UlteriusServer.Api.Network.Models.SystemInformation;
-
-#endregion
-
-namespace UlteriusServer.Utilities.Usage
-{
-    public class HardwareSurvey
-    {
-        private static readonly string results = "surveryresults.json";
-
-        private List<GpuInformation> GetGpuInformation()
-        {
-            var searcher =
-                new ManagementObjectSearcher("SELECT * FROM Win32_VideoController");
-
-            var gpus = (from ManagementBaseObject mo in searcher.Get()
-                select new GpuInformation
-                {
-                    Name = mo["Name"]?.ToString(),
-                    ScreenInfo = mo["VideoModeDescription"]?.ToString(),
-                    DriverVersion = mo["DriverVersion"]?.ToString(),
-                    RefreshRate = int.Parse(mo["CurrentRefreshRate"]?.ToString() ?? "0"),
-                    AdapterRam = mo["AdapterRAM"]?.ToString(),
-                    VideoArchitecture = int.Parse(mo["VideoArchitecture"]?.ToString() ?? "0"),
-                    VideoMemoryType = int.Parse(mo["VideoMemoryType"]?.ToString() ?? "0"),
-                    InstalledDisplayDrivers = mo["InstalledDisplayDrivers"]?.ToString()?.Split(','),
-                    AdapterCompatibility = mo["AdapterCompatibility"]?.ToString(),
-                    Status = mo["Status"]?.ToString(),
-                    Availability = int.Parse(mo["Availability"]?.ToString() ?? "0")
-                }).ToList();
-            return gpus;
-        }
-
-        private void Prompt()
-        {
-            var dialogResult = MessageBox.Show(Resources.HardwareSurvey_Setup_,
-                Resources.HardwareSurvey_Setup_Usage_statistics_reporting, MessageBoxButtons.YesNo);
-            switch (dialogResult)
-            {
-                case DialogResult.Yes:
-                    SendData();
-                    break;
-                case DialogResult.No:
-                    File.WriteAllText(results, "false");
-                    break;
-            }
-        }
-
-        public void Setup(bool service = false)
-        {
-            if (File.Exists(results))
-            {
-                var days = (DateTime.Now - File.GetCreationTime(results)).TotalDays;
-                if (days > 30)
-                {
-                    SendData();
-                }
-            }
-            else
-            {
-                if (service)
-                {
-                    SendData();
-                }
-                else
-                {
-                    Prompt();
-                }
-            }
-        }
-
-        public string GetMachineGuid()
-        {
-            try
-            {
-                var location = @"SOFTWARE\Microsoft\Cryptography";
-                var name = "MachineGuid";
-                using (var localMachineX64View =
-                    RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64))
-                {
-                    using (var rk = localMachineX64View.OpenSubKey(location))
-                    {
-                        if (rk == null)
-                            throw new KeyNotFoundException(
-                                $"Key Not Found: {location}");
-
-                        var machineGuid = rk.GetValue(name);
-                        if (machineGuid == null)
-                            throw new IndexOutOfRangeException(
-                                $"Index Not Found: {name}");
-                        return machineGuid.ToString().Replace("-", "").ToUpper();
-                    }
-                }
-            }
-            catch (Exception)
-            {
-                return Guid.NewGuid().ToString("N").ToUpper();
-            }
-        }
-
-        private async void SendData()
-        {
-            try
-            {
-                var data = new
-                {
-                    ServerInfo = OperatingSystemInformation.ToObject(),
-                    SystemInfo = SystemInformation.ToObject(),
-                    UlteriusVersion = Assembly.GetExecutingAssembly().GetName().Version,
-                    GpuInfo = GetGpuInformation(),
-                    NetworkInformation = NetworkInformation.ToObject(),
-                    CpuInfo = CpuInformation.ToObject()
-                };
-                var json = JsonConvert.SerializeObject(data);
-                var content = new FormUrlEncodedContent(new[]
-                {
-                    new KeyValuePair<string, string>("guid", GetMachineGuid()),
-                    new KeyValuePair<string, string>("results", json)
-                });
-                using (var client = new HttpClient())
-                {
-                    client.Timeout = new TimeSpan(0, 0, 0, 5);
-                    var result = await client.PostAsync("https://api.ulterius.io/hardware/", content);
-                    if (result.IsSuccessStatusCode)
-                    {
-                        Console.WriteLine("Hardware Survery Completed");
-                        File.WriteAllText(results, "true");
-                    }
-                }
-            }
-            catch (Exception)
-            {
-                //just fail
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/RemoteTaskServer/WebCams/WebCamManager.cs b/RemoteTaskServer/WebCams/WebCamManager.cs
index 47d3846..ee8a24b 100644
--- a/RemoteTaskServer/WebCams/WebCamManager.cs
+++ b/RemoteTaskServer/WebCams/WebCamManager.cs
@@ -8,11 +8,11 @@ using System.Drawing.Imaging;
 using System.IO;
 using System.Linq;
 using AForge.Video;
 using AForge.Video.DirectShow;
 using AForge.Vision.Motion;
-using AgentInterface.Settings;
+using UlteriusServer.Utilities;
 
 #endregion
 
 namespace UlteriusServer.WebCams
 {
diff --git a/RemoteTaskServer/WebServer/HttpServer.cs b/RemoteTaskServer/WebServer/HttpServer.cs
index 4c7aaec..a0e9334 100644
--- a/RemoteTaskServer/WebServer/HttpServer.cs
+++ b/RemoteTaskServer/WebServer/HttpServer.cs
@@ -7,14 +7,15 @@ using System.Linq;
 using System.Net;
 using System.Net.Sockets;
 using System.Text;
 using System.Threading;
 using System.Web;
-using AgentInterface.Settings;
 using Newtonsoft.Json;
 using UlteriusServer.Api.Services.Network;
 using UlteriusServer.Properties;
+using UlteriusServer.Utilities;
+using UlteriusServer.Utilities.Extensions;
 using UlteriusServer.Utilities.Files;
 using UlteriusServer.WebServer.RemoteTaskServer.WebServer;
 using File = System.IO.File;
 
 #endregion
@@ -284,17 +285,23 @@ namespace UlteriusServer.WebServer
                     break;
                 }
             }
 
             filename = HttpUtility.UrlDecode(Path.Combine(_rootDirectory, filename));
-
             if (File.Exists(filename))
             {
+               
                 try
                 {
+                    var targetPath = Path.GetDirectoryName(new DirectoryInfo(filename).FullName);
+                    //prevent directory traversal, we should only allow access to the root directory of the HTTP Server.
+                    if (!targetPath.IsSubPathOf(_rootDirectory))
+                    {
+                        context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
+                        return;
+                    }
                     Stream input = new FileStream(filename, FileMode.Open);
-
                     //Adding permanent http response headers
                     string mime;
 
                     context.Response.ContentType = MimeTypeMappings.TryGetValue(Path.GetExtension(filename),
                         out mime)
diff --git a/RemoteTaskServer/WebSocketAPI/WebSocketEventListener.cs b/RemoteTaskServer/WebSocketAPI/WebSocketEventListener.cs
index 6e52b68..7b60b3d 100644
--- a/RemoteTaskServer/WebSocketAPI/WebSocketEventListener.cs
+++ b/RemoteTaskServer/WebSocketAPI/WebSocketEventListener.cs
@@ -24,57 +24,43 @@ namespace UlteriusServer.WebSocketAPI
 
     public delegate void WebSocketEventListenerOnError(WebSocket webSocket, Exception error);
 
     public class WebSocketEventListener : IDisposable
     {
-        private readonly List<WebSocketListener> _listeners = new List<WebSocketListener>();
+        private WebSocketListener _listener;
 
-        public WebSocketEventListener(List<IPEndPoint> endpoints)
+        public WebSocketEventListener(Uri[] endpoints)
             : this(endpoints, new WebSocketListenerOptions())
         {
         }
 
-        public WebSocketEventListener(List<IPEndPoint> endpoints, WebSocketListenerOptions options)
+        public WebSocketEventListener(Uri[] endpoints, WebSocketListenerOptions options)
         {
-            foreach (var endpoint in endpoints)
-            {
-                var listener = new WebSocketListener(endpoint, options);
-                var rfc6455 = new WebSocketFactoryRfc6455(listener);
-                listener.Standards.RegisterStandard(rfc6455);
-                _listeners.Add(listener);
-            }
+            options.Standards.RegisterRfc6455();
+            _listener = new WebSocketListener(endpoints, options);
         }
 
         public void Dispose()
         {
-            foreach (var listener in _listeners)
-            {
-                listener.Dispose();
-            }
+            _listener?.StopAsync().GetAwaiter().GetResult();
         }
 
         public event WebSocketEventListenerOnConnect OnConnect;
         public event WebSocketEventListenerOnDisconnect OnDisconnect;
         public event WebSocketEventListenerOnEncryptedMessage OnEncryptedMessage;
         public event WebSocketEventListenerOnPlainTextMessage OnPlainTextMessage;
         public event WebSocketEventListenerOnError OnError;
 
-        public void Start()
+        public async void Start()
         {
-            foreach (var listener in _listeners)
-            {
-                listener.Start();
-            }
+            await _listener.StartAsync();
             ListenAsync();
         }
 
-        public void Stop()
+        public async void Stop()
         {
-            foreach (var listener in _listeners)
-            {
-                listener.Stop();
-            }
+            await _listener.StopAsync();
         }
 
         private async Task HandleListners(WebSocketListener listener)
         {
             while (listener.IsStarted)
@@ -93,14 +79,11 @@ namespace UlteriusServer.WebSocketAPI
             }
         }
 
         private void ListenAsync()
         {
-            foreach (var listener in _listeners)
-            {
-                Task.Run(() => HandleListners(listener));
-            }
+            Task.Run(() => HandleListners(_listener));
         }
 
         private async Task HandleWebSocketAsync(WebSocket websocket)
         {
             try
diff --git a/RemoteTaskServer/packages.config b/RemoteTaskServer/packages.config
index 14abec1..681595a 100644
--- a/RemoteTaskServer/packages.config
+++ b/RemoteTaskServer/packages.config
@@ -1,27 +1,30 @@
-﻿<?xml version="1.0" encoding="utf-8"?>
-<packages>
-  <package id="AForge" version="2.2.5" targetFramework="net461" />
-  <package id="AForge.Imaging" version="2.2.5" targetFramework="net461" />
-  <package id="AForge.Math" version="2.2.5" targetFramework="net461" />
-  <package id="AForge.Video" version="2.2.5" targetFramework="net461" />
-  <package id="AForge.Video.DirectShow" version="2.2.5" targetFramework="net461" />
-  <package id="AForge.Vision" version="2.2.5" targetFramework="net461" />
-  <package id="BouncyCastle" version="1.8.1" targetFramework="net461" />
-  <package id="Costura.Fody" version="2.0.0-beta0018" targetFramework="net461" developmentDependency="true" />
-  <package id="DotNetZip" version="1.10.1" targetFramework="net461" />
-  <package id="Fody" version="1.29.3" targetFramework="net461" developmentDependency="true" />
-  <package id="JonSkeet.MiscUtil" version="0.1" targetFramework="net45" />
-  <package id="log4net" version="2.0.7" targetFramework="net461" />
-  <package id="Magnum" version="2.1.3" targetFramework="net461" />
-  <package id="MassTransit" version="2.9.0" targetFramework="net461" />
-  <package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="1.0.3" targetFramework="net461" />
-  <package id="Microsoft.Net.Compilers" version="2.0.0-rc3" targetFramework="net461" developmentDependency="true" />
-  <package id="Microsoft.Tpl.Dataflow" version="4.5.24" targetFramework="net461" />
-  <package id="Mono.Cecil" version="0.9.6.4" targetFramework="net461" />
-  <package id="Newtonsoft.Json" version="10.0.1-beta1" targetFramework="net461" />
-  <package id="Open.NAT" version="2.1.0.0" targetFramework="net461" />
-  <package id="System.Threading.Tasks.Dataflow" version="4.7.0" targetFramework="net461" />
-  <package id="Topshelf" version="4.0.3" targetFramework="net461" />
-  <package id="vtortola.WebSocketListener" version="2.2.2.0" targetFramework="net461" />
-  <package id="ZetaLongPaths" version="1.0.0.14" targetFramework="net461" />
+﻿<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="AForge" version="2.2.5" targetFramework="net461" />
+  <package id="AForge.Imaging" version="2.2.5" targetFramework="net461" />
+  <package id="AForge.Math" version="2.2.5" targetFramework="net461" />
+  <package id="AForge.Video" version="2.2.5" targetFramework="net461" />
+  <package id="AForge.Video.DirectShow" version="2.2.5" targetFramework="net461" />
+  <package id="AForge.Vision" version="2.2.5" targetFramework="net461" />
+  <package id="BouncyCastle" version="1.8.1" targetFramework="net461" />
+  <package id="deniszykov.WebSocketListener" version="4.0.0" targetFramework="net461" />
+  <package id="DotNetZip" version="1.10.1" targetFramework="net461" />
+  <package id="JonSkeet.MiscUtil" version="0.2.0" targetFramework="net461" />
+  <package id="log4net" version="2.0.8" targetFramework="net461" />
+  <package id="Magnum" version="2.1.3" targetFramework="net461" />
+  <package id="MassTransit" version="2.9.0" targetFramework="net461" />
+  <package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="1.0.3" targetFramework="net461" />
+  <package id="Microsoft.Net.Compilers" version="2.4.0" targetFramework="net461" developmentDependency="true" />
+  <package id="Microsoft.Tpl.Dataflow" version="4.5.24" targetFramework="net461" />
+  <package id="Mono.Cecil" version="0.9.6.4" targetFramework="net461" />
+  <package id="Newtonsoft.Json" version="10.0.3" targetFramework="net461" />
+  <package id="Open.NAT" version="2.1.0.0" targetFramework="net461" />
+  <package id="SharpDX" version="4.0.1" targetFramework="net461" />
+  <package id="SharpDX.Direct3D11" version="4.0.1" targetFramework="net461" />
+  <package id="SharpDX.DXGI" version="4.0.1" targetFramework="net461" />
+  <package id="SharpDX.Mathematics" version="4.0.1" targetFramework="net461" />
+  <package id="System.Threading.Tasks.Dataflow" version="4.8.0" targetFramework="net461" />
+  <package id="Topshelf" version="4.0.3" targetFramework="net461" />
+  <package id="TurboJpegWrapper" version="1.4.2.6" targetFramework="net461" />
+  <package id="ZetaLongPaths" version="1.0.0.19" targetFramework="net461" />
 </packages>
\ No newline at end of file
diff --git a/UlteriusAgent/App.config b/UlteriusAgent/App.config
index 4c129f4..07549d0 100644
--- a/UlteriusAgent/App.config
+++ b/UlteriusAgent/App.config
@@ -1,22 +1,22 @@
-﻿<?xml version="1.0" encoding="utf-8"?>
-<configuration>
-    <startup> 
-        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
-    </startup>
-  <runtime>
-    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
-      <dependentAssembly>
-        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
-      </dependentAssembly>
-      <dependentAssembly>
-        <assemblyIdentity name="Magnum" publicKeyToken="b800c4cfcdeea87b" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-2.1.3.0" newVersion="2.1.3.0" />
-      </dependentAssembly>
-      <dependentAssembly>
-        <assemblyIdentity name="AsyncIO" publicKeyToken="44a94435bd6f33f8" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-0.1.25.0" newVersion="0.1.25.0" />
-      </dependentAssembly>
-    </assemblyBinding>
-  </runtime>
-</configuration>
\ No newline at end of file
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+    <startup> 
+        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1"/>
+    </startup>
+  <runtime>
+    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+      <dependentAssembly>
+        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
+        <bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0"/>
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Magnum" publicKeyToken="b800c4cfcdeea87b" culture="neutral"/>
+        <bindingRedirect oldVersion="0.0.0.0-2.1.3.0" newVersion="2.1.3.0"/>
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="AsyncIO" publicKeyToken="44a94435bd6f33f8" culture="neutral"/>
+        <bindingRedirect oldVersion="0.0.0.0-0.1.25.0" newVersion="0.1.25.0"/>
+      </dependentAssembly>
+    </assemblyBinding>
+  </runtime>
+</configuration>
diff --git a/UlteriusAgent/FodyWeavers.xml b/UlteriusAgent/FodyWeavers.xml
deleted file mode 100644
index dd5af76..0000000
--- a/UlteriusAgent/FodyWeavers.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-﻿<?xml version="1.0" encoding="utf-8"?>
-<Weavers>
-  <Costura>
-    <ExcludeAssemblies>
-      WindowsInput
-      AgentInterface
-      Newtonsoft.Json
-    </ExcludeAssemblies>
-  </Costura>
-</Weavers>
\ No newline at end of file
diff --git a/UlteriusAgent/Networking/FrameAgent.cs b/UlteriusAgent/Networking/FrameAgent.cs
deleted file mode 100644
index 6dcd81a..0000000
--- a/UlteriusAgent/Networking/FrameAgent.cs
+++ /dev/null
@@ -1,87 +0,0 @@
-﻿#region
-
-using System;
-using System.Drawing;
-using System.ServiceModel;
-using AgentInterface;
-using AgentInterface.Api.Models;
-using AgentInterface.Api.ScreenShare;
-using AgentInterface.Api.Win32;
-
-
-#endregion
-
-namespace UlteriusAgent.Networking
-{
-    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
-    public class FrameAgent : IFrameContract
-    {
-        private string _lastDesktop;
-        private Desktop _lastDesktopInput;
-
-
-        public FrameInformation GetCleanFrame()
-        {
-            HandleDesktop();
-            var setCurrent = Desktop.SetCurrent(_lastDesktopInput);
-            return !setCurrent ? null : ScreenData.DesktopCapture();
-        }
-
-        public FrameInformation GetFullFrame()
-        {
-            HandleDesktop();
-            var tempBounds = Display.GetWindowRectangle();
-            var frameInfo = new FrameInformation
-            {
-                Bounds = tempBounds,
-                ScreenImage = ScreenData.CaptureDesktop()
-            };
-            if (frameInfo.ScreenImage != null) return frameInfo;
-            var bmp = new Bitmap(frameInfo.Bounds.Width, frameInfo.Bounds.Height);
-            using (var gfx = Graphics.FromImage(bmp))
-            using (var brush = new SolidBrush(Color.FromArgb(67, 75, 99)))
-            {
-                gfx.FillRectangle(brush, 0, 0, frameInfo.Bounds.Width, frameInfo.Bounds.Height);
-            }
-            frameInfo.ScreenImage = bmp;
-            return frameInfo;
-        }
-
-        public bool KeepAlive()
-        {
-            return true;
-        }
-
-        private void HandleDesktop()
-        {
-            using (var inputDesktop = new Desktop())
-            {
-                inputDesktop.OpenInput();
-                if (!inputDesktop.DesktopName.Equals(_lastDesktop))
-                {
-                    var switched = inputDesktop.Show();
-
-                    if (switched)
-                    {
-                        var setCurrent = Desktop.SetCurrent(inputDesktop);
-                        if (setCurrent)
-                        {
-                            Console.WriteLine($"Desktop switched from {_lastDesktop} to {inputDesktop.DesktopName}");
-                            _lastDesktop = inputDesktop.DesktopName;
-                            _lastDesktopInput = inputDesktop;
-                        }
-                        else
-                        {
-                            _lastDesktopInput.Close();
-                        }
-                    }
-                }
-                else
-                {
-                    inputDesktop.Close();
-                }
-            }
-           
-        }
-    }
-}
\ No newline at end of file
diff --git a/UlteriusAgent/Networking/InputAgent.cs b/UlteriusAgent/Networking/InputAgent.cs
deleted file mode 100644
index 89bd962..0000000
--- a/UlteriusAgent/Networking/InputAgent.cs
+++ /dev/null
@@ -1,159 +0,0 @@
-﻿using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Runtime.ExceptionServices;
-using System.ServiceModel;
-using System.Text;
-using System.Threading.Tasks;
-using WindowsInput;
-using WindowsInput.Native;
-using AgentInterface;
-using AgentInterface.Api.Models;
-using AgentInterface.Api.System;
-using AgentInterface.Api.Win32;
-
-namespace UlteriusAgent.Networking
-{
-    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
-    public class InputAgent : IInputContract
-    {
-
-        public void HandleRightMouseDown()
-        {
-            var inputDesktop = new Desktop();
-            inputDesktop.OpenInput();
-            var setCurrent = Desktop.SetCurrent(inputDesktop);
-            if (setCurrent)
-            {
-                new InputSimulator().Mouse.RightButtonDown();
-            }
-        }
-
-        public void HandleRightMouseUp()
-        {
-            var inputDesktop = new Desktop();
-            inputDesktop.OpenInput();
-            var setCurrent = Desktop.SetCurrent(inputDesktop);
-            if (setCurrent)
-            {
-                new InputSimulator().Mouse.RightButtonUp();
-            }
-
-        }
-
-        public void MoveMouse(int x, int y)
-        {
-            var inputDesktop = new Desktop();
-            inputDesktop.OpenInput();
-            var setCurrent = Desktop.SetCurrent(inputDesktop);
-            if (setCurrent)
-            {
-                var bounds = Display.GetWindowRectangle();
-                x = checked((int)Math.Round(x * (65535 / (double)bounds.Width)));
-                y = checked((int)Math.Round(y * (65535 / (double)bounds.Height)));
-                new InputSimulator().Mouse.MoveMouseTo(x, y);
-            }
-        }
-
-        public void MouseScroll(bool positive)
-        {
-            var inputDesktop = new Desktop();
-            inputDesktop.OpenInput();
-            var setCurrent = Desktop.SetCurrent(inputDesktop);
-            if (setCurrent)
-            {
-                var direction = positive ? 10 : -10;
-                new InputSimulator().Mouse.VerticalScroll(direction);
-            }
-
-        }
-
-
-        public void HandleLeftMouseDown()
-        {
-            var inputDesktop = new Desktop();
-            inputDesktop.OpenInput();
-            var setCurrent = Desktop.SetCurrent(inputDesktop);
-            if (setCurrent)
-            {
-                new InputSimulator().Mouse.LeftButtonDown();
-            }
-
-
-        }
-
-        public void HandleLeftMouseUp()
-        {
-            var inputDesktop = new Desktop();
-            inputDesktop.OpenInput();
-            var setCurrent = Desktop.SetCurrent(inputDesktop);
-            if (setCurrent)
-            {
-                new InputSimulator().Mouse.LeftButtonUp();
-            }
-
-
-        }
-
-        public void HandleKeyDown(List<int> keyCodes)
-        {
-            var inputDesktop = new Desktop();
-            inputDesktop.OpenInput();
-            var setCurrent = Desktop.SetCurrent(inputDesktop);
-            if (setCurrent)
-            {
-                foreach (var code in keyCodes)
-                {
-                    var virtualKey = (VirtualKeyCode)code;
-                    new InputSimulator().Keyboard.KeyDown(virtualKey);
-
-                }
-            }
-
-        }
-
-        public void HandleKeyUp(List<int> keyCodes)
-        {
-            var inputDesktop = new Desktop();
-            inputDesktop.OpenInput();
-            var setCurrent = Desktop.SetCurrent(inputDesktop);
-            if (setCurrent)
-            {
-                foreach (var code in keyCodes)
-                {
-                    var virtualKey = (VirtualKeyCode)code;
-                    new InputSimulator().Keyboard.KeyUp(virtualKey);
-                }
-            }
-
-        }
-
-        public void HandleRightClick()
-        {
-            var inputDesktop = new Desktop();
-            inputDesktop.OpenInput();
-            var setCurrent = Desktop.SetCurrent(inputDesktop);
-            if (setCurrent)
-            {
-                new InputSimulator().Mouse.RightButtonClick();
-            }
-        }
-
-        [HandleProcessCorruptedStateExceptions]
-        public float GetGpuTemp(string gpuName)
-        {
-            return SystemData.GetGpuTemp(gpuName);
-        }
-
-        public List<DisplayInformation> GetDisplayInformation()
-        {
-            return Display.DisplayInformation();
-        }
-
-
-        public List<float> GetCpuTemps()
-        {
-            return SystemData.GetCpuTemps();
-        }
-    }
-}
diff --git a/UlteriusAgent/Networking/Tools.cs b/UlteriusAgent/Networking/Tools.cs
deleted file mode 100644
index e076639..0000000
--- a/UlteriusAgent/Networking/Tools.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-﻿#region
-
-using System;
-using System.Diagnostics;
-using System.Linq;
-
-#endregion
-
-namespace UlteriusAgent.Networking
-{
-    public static class Tools
-    {
-        public static void KillAllButMe()
-        {
-            try
-            {
-                var current = Process.GetCurrentProcess();
-                //kill any other agent that may be running
-                var processes = Process.GetProcessesByName(current.ProcessName)
-                    .Where(t => t.Id != current.Id)
-                    .ToList();
-                foreach (var process in processes)
-                {
-                    process.Kill();
-                    process.WaitForExit();
-                }
-            }
-            catch (Exception)
-            {
-                // ignored
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/UlteriusAgent/Program.cs b/UlteriusAgent/Program.cs
index cc4f4aa..39a12a7 100644
--- a/UlteriusAgent/Program.cs
+++ b/UlteriusAgent/Program.cs
@@ -1,101 +1,44 @@
 ﻿#region
 
-using System;
-using System.Collections.ObjectModel;
-using System.Net.Security;
-using System.Runtime.InteropServices;
-using System.ServiceModel;
-using System.ServiceModel.Channels;
-using System.ServiceModel.Description;
-using System.ServiceModel.Dispatcher;
-using AgentInterface;
-using AgentInterface.Api.ScreenShare;
-using UlteriusAgent.Networking;
+using Topshelf;
+using Warden.Core;
 
 #endregion
 
 namespace UlteriusAgent
 {
-  
 
     internal class Program
     {
-        private const int SW_HIDE = 0;
-        private const int SW_SHOW = 5;
-
-        [DllImport("user32.dll")]
-        private static extern bool SetProcessDPIAware();
-
-        [DllImport("kernel32.dll")]
-        private static extern IntPtr GetConsoleWindow();
-
-        [DllImport("user32.dll")]
-        private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
-
-
         private static void Main(string[] args)
         {
-            if (Environment.OSVersion.Version.Major >= 6)
+            WardenManager.Initialize(new WardenOptions
             {
-                SetProcessDPIAware();
-            }
-            var handle = GetConsoleWindow();
-
-            // Hide
-            ShowWindow(handle, SW_HIDE);
-
-            Tools.KillAllButMe();
-            try
+                DeepKill = true,
+                CleanOnExit = true,
+                ReadFileHeaders = false
+            });
+            HostFactory.Run(x => //1
             {
-                ScreenData.SetupDuplication();
-                var inputAddress = "net.tcp://localhost/ulterius/agent/input/";
-                var frameAddress = "net.pipe://localhost/ulterius/agent/frames/";
-               
-                var inputService = new ServiceHost(typeof(InputAgent));
-                var frameService = new ServiceHost(typeof(FrameAgent));
-                var inputBinding = new NetTcpBinding
-                {
-                    Security = new NetTcpSecurity
-                    {
-                        Transport = {ProtectionLevel = ProtectionLevel.None},
-                        Mode = SecurityMode.None
-                    },
-                    MaxReceivedMessageSize = int.MaxValue
-                };
-                var frameBinding = new NetNamedPipeBinding
+                x.Service<UlteriusAgent>(s => //2
                 {
-                    Security = new NetNamedPipeSecurity
-                    {
-                        Transport = { ProtectionLevel = ProtectionLevel.None },
-                        Mode = NetNamedPipeSecurityMode.None
-                    },
-                    MaxReceivedMessageSize = int.MaxValue
-                };
-                inputService.AddServiceEndpoint(typeof(IInputContract), inputBinding, inputAddress);
-                frameService.AddServiceEndpoint(typeof(IFrameContract), frameBinding, frameAddress);
-                inputService.Opened += delegate(object sender, EventArgs eventArgs)
-                 {
-                     Console.WriteLine("Input started");
-                 };
-                frameService.Opened += delegate (object sender, EventArgs eventArgs)
+                    s.ConstructUsing(name => new UlteriusAgent()); //3
+                    s.WhenStarted(tc => tc.Start()); //4
+                    s.WhenStopped(tc => tc.Stop());
+                    s.WhenSessionChanged((se, e, id) => { se.HandleEvent(e, id); }); //5
+                });
+                x.OnException(ex =>
                 {
-                    Console.WriteLine("Frame started");
-                };
-                inputService.Open();
-                frameService.Open();
-                Console.WriteLine("Test");
-                Console.Read();
-            }
-            catch (Exception ex)
-            {
-                Console.WriteLine(ex.Message + " \n " + ex.StackTrace);
-            }
-            Console.Read();
-        }
-
-        private static void host_faulted(object sender, EventArgs e)
-        {
-            
+                    //TODO Logging
+                });
+                x.RunAsLocalSystem(); //6
+                x.EnableSessionChanged();
+                x.EnableServiceRecovery(r => { r.RestartService(1); });
+                x.SetDescription("The server that powers Ulterius"); //7
+                x.SetDisplayName("Ulterius Server"); //8
+                x.SetServiceName("UlteriusServer"); //9
+                x.StartAutomaticallyDelayed();
+            });
         }
     }
 }
\ No newline at end of file
diff --git a/UlteriusAgent/UlteriusAgent.cs b/UlteriusAgent/UlteriusAgent.cs
new file mode 100644
index 0000000..d02fccd
--- /dev/null
+++ b/UlteriusAgent/UlteriusAgent.cs
@@ -0,0 +1,107 @@
+﻿using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Topshelf;
+using Warden.Core;
+using Warden.Core.Utils;
+
+namespace UlteriusAgent
+{
+    public class UlteriusAgent
+    {
+        private readonly string _ulteriusPath;
+        private WardenProcess _ulteriusInstance;
+
+
+        public UlteriusAgent()
+        {
+            const string ulteriusFileName = "Ulterius Server.exe";
+            _ulteriusPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ulteriusFileName);
+        }
+
+        public void Start()
+        {
+            if (!File.Exists(_ulteriusPath))
+            {
+                throw new InvalidOperationException($"Unable to locate Ulterius at {_ulteriusPath}");
+            }
+            if (Respawn())
+            {
+                Console.WriteLine("Rainway started as a service!");
+                Console.ReadLine();
+            }
+            else
+            {
+                Console.WriteLine("Failed to start Rainway!");
+                Environment.Exit(1);
+            }
+        }
+
+        private bool Respawn()
+        {
+            _ulteriusInstance = null;
+            _ulteriusInstance = WardenProcess.Start(_ulteriusPath, string.Empty, null, true).GetAwaiter().GetResult();
+            if (_ulteriusInstance == null || !_ulteriusInstance.IsTreeActive())
+            {
+                return false;
+            }
+            _ulteriusInstance.OnStateChange += UlteriusInstanceOnOnStateChange;
+            return true;
+        }
+
+        public void Stop()
+        {
+            const string ulteriusFileName = "Ulterius Server.exe";
+            if (_ulteriusInstance != null)
+            {
+                _ulteriusInstance?.Kill();
+                WardenManager.Flush(_ulteriusInstance.Id);
+            }
+            _ulteriusInstance = null;
+            EndProcessTree(ulteriusFileName);
+        }
+
+        private void EndProcessTree(string imageName)
+        {
+            try
+            {
+                var taskKill = new TaskKill
+                {
+                    Arguments = new List<TaskSwitch>()
+                    {
+                        TaskSwitch.Force,
+                        TaskSwitch.TerminateChildren,
+                        TaskSwitch.ImageName.SetValue(imageName)
+                    }
+                };
+                taskKill.Execute(out var output, out var errror);
+            }
+            catch
+            {
+                //
+            }
+        }
+
+        private void UlteriusInstanceOnOnStateChange(object sender, StateEventArgs stateEventArgs)
+        {
+            if (stateEventArgs.Id == _ulteriusInstance.Id && stateEventArgs.State == ProcessState.Dead)
+            {
+                //Kill the entire tree.
+                _ulteriusInstance.Kill();
+                WardenManager.Flush(_ulteriusInstance.Id);
+                if (Respawn())
+                {
+                   Console.WriteLine("Rainway restarted!");
+                }
+            }
+        }
+
+        public void HandleEvent(HostControl hostControl, SessionChangedArguments arg3)
+        {
+            
+        }
+    }
+}
diff --git a/UlteriusAgent/UlteriusAgent.csproj b/UlteriusAgent/UlteriusAgent.csproj
index 730ede3..1c07b1b 100644
--- a/UlteriusAgent/UlteriusAgent.csproj
+++ b/UlteriusAgent/UlteriusAgent.csproj
@@ -1,121 +1,71 @@
-﻿<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
-  <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProjectGuid>{686AE4C4-791F-45EB-9414-029D6115905D}</ProjectGuid>
-    <OutputType>Exe</OutputType>
-    <AppDesignerFolder>Properties</AppDesignerFolder>
-    <RootNamespace>UlteriusAgent</RootNamespace>
-    <AssemblyName>UlteriusAgent</AssemblyName>
-    <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
-    <FileAlignment>512</FileAlignment>
-    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
-    <NuGetPackageImportStamp>
-    </NuGetPackageImportStamp>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <PlatformTarget>AnyCPU</PlatformTarget>
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <PlatformTarget>AnyCPU</PlatformTarget>
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <Prefer32Bit>false</Prefer32Bit>
-  </PropertyGroup>
-  <PropertyGroup>
-    <StartupObject />
-  </PropertyGroup>
-  <PropertyGroup>
-    <ApplicationManifest>app.manifest</ApplicationManifest>
-  </PropertyGroup>
-  <ItemGroup>
-    <Reference Include="System" />
-    <Reference Include="System.Core" />
-    <Reference Include="System.Drawing" />
-    <Reference Include="System.ServiceModel" />
-    <Reference Include="System.Windows.Forms" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="Networking\InputAgent.cs" />
-    <Compile Include="Networking\FrameAgent.cs" />
-    <Compile Include="Networking\Tools.cs" />
-    <Compile Include="Program.cs" />
-    <Compile Include="Properties\AssemblyInfo.cs" />
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="App.config">
-      <SubType>Designer</SubType>
-    </None>
-    <None Include="app.manifest" />
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="FodyWeavers.xml" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="..\..\inputsimulator2\WindowsInput\WindowsInput.csproj">
-      <Project>{3549cd6f-80f8-450f-b99e-cf0a736b1f2a}</Project>
-      <Name>WindowsInput</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\AgentInterface\AgentInterface.csproj">
-      <Project>{5c3b0b17-cbb7-4b4b-b527-1fab2bb96466}</Project>
-      <Name>AgentInterface</Name>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
-  <UsingTask TaskName="CosturaCleanup" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" TaskFactory="CodeTaskFactory">
-    <ParameterGroup>
-      <Config Output="false" Required="true" ParameterType="Microsoft.Build.Framework.ITaskItem" />
-      <Files Output="false" Required="true" ParameterType="Microsoft.Build.Framework.ITaskItem[]" />
-    </ParameterGroup>
-    <Task Evaluate="true">
-      <Reference xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Include="System.Xml" />
-      <Reference xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Include="System.Xml.Linq" />
-      <Using xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Namespace="System" />
-      <Using xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Namespace="System.IO" />
-      <Using xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Namespace="System.Xml.Linq" />
-      <Code xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Type="Fragment" Language="cs"><![CDATA[
-var config = XElement.Load(Config.ItemSpec).Elements("Costura").FirstOrDefault();
-
-if (config == null) return true;
-
-var excludedAssemblies = new List<string>();
-var attribute = config.Attribute("ExcludeAssemblies");
-if (attribute != null)
-    foreach (var item in attribute.Value.Split('|').Select(x => x.Trim()).Where(x => x != string.Empty))
-        excludedAssemblies.Add(item);
-var element = config.Element("ExcludeAssemblies");
-if (element != null)
-    foreach (var item in element.Value.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()).Where(x => x != string.Empty))
-        excludedAssemblies.Add(item);
-
-var filesToCleanup = Files.Select(f => f.ItemSpec).Where(f => !excludedAssemblies.Contains(Path.GetFileNameWithoutExtension(f), StringComparer.InvariantCultureIgnoreCase));
-
-foreach (var item in filesToCleanup)
-  File.Delete(item);
-]]></Code>
-    </Task>
-  </UsingTask>
-  <Target Name="CleanReferenceCopyLocalPaths" AfterTargets="AfterBuild;NonWinFodyTarget">
-    <CosturaCleanup Config="FodyWeavers.xml" Files="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" />
-  </Target>
-  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
-       Other similar extension points exist, see Microsoft.Common.targets.
-  <Target Name="BeforeBuild">
-  </Target>
-  <Target Name="AfterBuild">
-  </Target>
-  -->
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{686AE4C4-791F-45EB-9414-029D6115905D}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>UlteriusAgent</RootNamespace>
+    <AssemblyName>UlteriusAgent</AssemblyName>
+    <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
+    <NuGetPackageImportStamp>
+    </NuGetPackageImportStamp>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <LangVersion>7</LangVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
+    <LangVersion>7</LangVersion>
+  </PropertyGroup>
+  <PropertyGroup>
+    <StartupObject />
+  </PropertyGroup>
+  <PropertyGroup>
+    <ApplicationManifest>app.manifest</ApplicationManifest>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="Topshelf, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b800c4cfcdeea87b, processorArchitecture=MSIL">
+      <HintPath>..\packages\Topshelf.4.0.3\lib\net452\Topshelf.dll</HintPath>
+    </Reference>
+    <Reference Include="Warden, Version=1.2.3.0, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\Warden.NET.1.2.3\lib\net45\Warden.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="UlteriusAgent.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="App.config">
+      <SubType>Designer</SubType>
+    </None>
+    <None Include="app.manifest" />
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
 </Project>
\ No newline at end of file
diff --git a/UlteriusAgent/packages.config b/UlteriusAgent/packages.config
new file mode 100644
index 0000000..1c40d5b
--- /dev/null
+++ b/UlteriusAgent/packages.config
@@ -0,0 +1,5 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="Topshelf" version="4.0.3" targetFramework="net452" />
+  <package id="Warden.NET" version="1.2.3" targetFramework="net452" />
+</packages>
\ No newline at end of file
diff --git a/UlteriusServer.sln b/UlteriusServer.sln
index 87dc310..c327ab5 100644
--- a/UlteriusServer.sln
+++ b/UlteriusServer.sln
@@ -1,49 +1,44 @@
-﻿
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 14
-VisualStudioVersion = 14.0.25420.1
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UlteriusServer", "RemoteTaskServer\UlteriusServer.csproj", "{E9A365D5-AEBE-4AF3-86C5-D17BC65ADE46}"
-	ProjectSection(ProjectDependencies) = postProject
-		{5C3B0B17-CBB7-4B4B-B527-1FAB2BB96466} = {5C3B0B17-CBB7-4B4B-B527-1FAB2BB96466}
-		{3549CD6F-80F8-450F-B99E-CF0A736B1F2A} = {3549CD6F-80F8-450F-B99E-CF0A736B1F2A}
-		{686AE4C4-791F-45EB-9414-029D6115905D} = {686AE4C4-791F-45EB-9414-029D6115905D}
-	EndProjectSection
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UlteriusAgent", "UlteriusAgent\UlteriusAgent.csproj", "{686AE4C4-791F-45EB-9414-029D6115905D}"
-	ProjectSection(ProjectDependencies) = postProject
-		{5C3B0B17-CBB7-4B4B-B527-1FAB2BB96466} = {5C3B0B17-CBB7-4B4B-B527-1FAB2BB96466}
-		{3549CD6F-80F8-450F-B99E-CF0A736B1F2A} = {3549CD6F-80F8-450F-B99E-CF0A736B1F2A}
-	EndProjectSection
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AgentInterface", "AgentInterface\AgentInterface.csproj", "{5C3B0B17-CBB7-4B4B-B527-1FAB2BB96466}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsInput", "..\inputsimulator2\WindowsInput\WindowsInput.csproj", "{3549CD6F-80F8-450F-B99E-CF0A736B1F2A}"
-EndProject
-Global
-	GlobalSection(SolutionConfigurationPlatforms) = preSolution
-		Debug|Any CPU = Debug|Any CPU
-		Release|Any CPU = Release|Any CPU
-	EndGlobalSection
-	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{E9A365D5-AEBE-4AF3-86C5-D17BC65ADE46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{E9A365D5-AEBE-4AF3-86C5-D17BC65ADE46}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{E9A365D5-AEBE-4AF3-86C5-D17BC65ADE46}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{E9A365D5-AEBE-4AF3-86C5-D17BC65ADE46}.Release|Any CPU.Build.0 = Release|Any CPU
-		{686AE4C4-791F-45EB-9414-029D6115905D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{686AE4C4-791F-45EB-9414-029D6115905D}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{686AE4C4-791F-45EB-9414-029D6115905D}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{686AE4C4-791F-45EB-9414-029D6115905D}.Release|Any CPU.Build.0 = Release|Any CPU
-		{5C3B0B17-CBB7-4B4B-B527-1FAB2BB96466}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{5C3B0B17-CBB7-4B4B-B527-1FAB2BB96466}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{5C3B0B17-CBB7-4B4B-B527-1FAB2BB96466}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{5C3B0B17-CBB7-4B4B-B527-1FAB2BB96466}.Release|Any CPU.Build.0 = Release|Any CPU
-		{3549CD6F-80F8-450F-B99E-CF0A736B1F2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{3549CD6F-80F8-450F-B99E-CF0A736B1F2A}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{3549CD6F-80F8-450F-B99E-CF0A736B1F2A}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{3549CD6F-80F8-450F-B99E-CF0A736B1F2A}.Release|Any CPU.Build.0 = Release|Any CPU
-	EndGlobalSection
-	GlobalSection(SolutionProperties) = preSolution
-		HideSolutionNode = FALSE
-	EndGlobalSection
-EndGlobal
+﻿
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.27004.2005
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UlteriusServer", "RemoteTaskServer\UlteriusServer.csproj", "{E9A365D5-AEBE-4AF3-86C5-D17BC65ADE46}"
+	ProjectSection(ProjectDependencies) = postProject
+		{3549CD6F-80F8-450F-B99E-CF0A736B1F2A} = {3549CD6F-80F8-450F-B99E-CF0A736B1F2A}
+		{686AE4C4-791F-45EB-9414-029D6115905D} = {686AE4C4-791F-45EB-9414-029D6115905D}
+	EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UlteriusAgent", "UlteriusAgent\UlteriusAgent.csproj", "{686AE4C4-791F-45EB-9414-029D6115905D}"
+	ProjectSection(ProjectDependencies) = postProject
+		{3549CD6F-80F8-450F-B99E-CF0A736B1F2A} = {3549CD6F-80F8-450F-B99E-CF0A736B1F2A}
+	EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsInput", "..\..\..\inputsimulator2\WindowsInput\WindowsInput.csproj", "{3549CD6F-80F8-450F-B99E-CF0A736B1F2A}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{E9A365D5-AEBE-4AF3-86C5-D17BC65ADE46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{E9A365D5-AEBE-4AF3-86C5-D17BC65ADE46}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{E9A365D5-AEBE-4AF3-86C5-D17BC65ADE46}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{E9A365D5-AEBE-4AF3-86C5-D17BC65ADE46}.Release|Any CPU.Build.0 = Release|Any CPU
+		{686AE4C4-791F-45EB-9414-029D6115905D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{686AE4C4-791F-45EB-9414-029D6115905D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{686AE4C4-791F-45EB-9414-029D6115905D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{686AE4C4-791F-45EB-9414-029D6115905D}.Release|Any CPU.Build.0 = Release|Any CPU
+		{3549CD6F-80F8-450F-B99E-CF0A736B1F2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{3549CD6F-80F8-450F-B99E-CF0A736B1F2A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{3549CD6F-80F8-450F-B99E-CF0A736B1F2A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{3549CD6F-80F8-450F-B99E-CF0A736B1F2A}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {9CC02739-8FB9-4530-9C74-0436AF2D60A7}
+	EndGlobalSection
+EndGlobal

Vulnerable code: ﻿<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{5C3B0B17-CBB7-4B4B-B527-1FAB2BB96466}</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>AgentInterface</RootNamespace>
    <AssemblyName>AgentInterface</AssemblyName>
    <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
    <NuGetPackageImportStamp>
    </NuGetPackageImportStamp>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
  </PropertyGroup>
  <PropertyGroup>
    <SignAssembly>true</SignAssembly>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="Cassia, Version=2.0.0.60, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\packages\Cassia.2.0.0.60\lib\2.0\Cassia.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
      <HintPath>..\packages\Newtonsoft.Json.10.0.1-beta1\lib\net45\Newtonsoft.Json.dll</HintPath>
    </Reference>
    <Reference Include="OpenHardwareMonitorLib, Version=0.7.1.0, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\packages\OpenHardwareMonitor.0.7.1\lib\net40\OpenHardwareMonitorLib.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="PresentationCore" />
    <Reference Include="PresentationFramework" />
    <Reference Include="SharpDX, Version=3.1.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
      <HintPath>..\packages\SharpDX.3.1.1\lib\net45\SharpDX.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="SharpDX.Direct3D11, Version=3.1.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
      <HintPath>..\packages\SharpDX.Direct3D11.3.1.1\lib\net45\SharpDX.Direct3D11.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="SharpDX.DXGI, Version=3.1.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
      <HintPath>..\packages\SharpDX.DXGI.3.1.1\lib\net45\SharpDX.DXGI.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="SharpDX.Mathematics, Version=3.1.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
      <HintPath>..\packages\SharpDX.Mathematics.3.1.1\lib\net45\SharpDX.Mathematics.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="System.Drawing" />
    <Reference Include="System.Runtime.Serialization" />
    <Reference Include="System.ServiceModel" />
    <Reference Include="System.Windows.Forms" />
    <Reference Include="TurboJpegWrapper, Version=1.4.2.19498, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\packages\TurboJpegWrapper.1.4.2.6\lib\net35\TurboJpegWrapper.dll</HintPath>
    </Reference>
    <Reference Include="WindowsBase" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Api\Models\DisplayInformation.cs" />
    <Compile Include="Api\Models\FrameInformation.cs" />
    <Compile Include="Api\Models\ResolutionInformation.cs" />
    <Compile Include="Api\ScreenShare\DesktopDuplication\DesktopDuplicationException.cs" />
    <Compile Include="Api\ScreenShare\DesktopDuplication\DesktopDuplicator.cs" />
    <Compile Include="Api\ScreenShare\DesktopDuplication\DesktopFrame.cs" />
    <Compile Include="Api\ScreenShare\DesktopDuplication\MovedRegion.cs" />
    <Compile Include="Api\ScreenShare\DesktopDuplication\FinishedRegions.cs" />
    <Compile Include="Api\ScreenShare\ScreenData.cs" />
    <Compile Include="Api\System\SystemData.cs" />
    <Compile Include="Api\Win32\Desktop.cs" />
    <Compile Include="Api\Win32\Display.cs" />
    <Compile Include="Api\Win32\ProcessStarter.cs" />
    <Compile Include="Api\Win32\SessionInfo.cs" />
    <Compile Include="Api\Win32\Win32Exception.cs" />
    <Compile Include="Api\Win32\WinApi.cs" />
    <Compile Include="Api\Win32\WindowsIdentityImpersonator.cs" />
    <Compile Include="FrameContract.cs" />
    <Compile Include="InputContract.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
    <Compile Include="Settings\AppEnvironment.cs" />
    <Compile Include="Settings\Config.cs" />
  </ItemGroup>
  <ItemGroup>
    <None Include="packages.config" />
  </ItemGroup>
  <ItemGroup>
    <None Include="FodyWeavers.xml">
      <SubType>Designer</SubType>
    </None>
  </ItemGroup>
  <ItemGroup />
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <UsingTask TaskName="CosturaCleanup" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" TaskFactory="CodeTaskFactory">
    <ParameterGroup>
      <Config Output="false" Required="true" ParameterType="Microsoft.Build.Framework.ITaskItem" />
      <Files Output="false" Required="true" ParameterType="Microsoft.Build.Framework.ITaskItem[]" />
    </ParameterGroup>
    <Task Evaluate="true">
      <Reference xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Include="System.Xml" />
      <Reference xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Include="System.Xml.Linq" />
      <Using xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Namespace="System" />
      <Using xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Namespace="System.IO" />
      <Using xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Namespace="System.Xml.Linq" />
      <Code xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Type="Fragment" Language="cs"><![CDATA[
var config = XElement.Load(Config.ItemSpec).Elements("Costura").FirstOrDefault();

if (config == null) return true;

var excludedAssemblies = new List<string>();
var attribute = config.Attribute("ExcludeAssemblies");
if (attribute != null)
    foreach (var item in attribute.Value.Split('|').Select(x => x.Trim()).Where(x => x != string.Empty))
        excludedAssemblies.Add(item);
var element = config.Element("ExcludeAssemblies");
if (element != null)
    foreach (var item in element.Value.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()).Where(x => x != string.Empty))
        excludedAssemblies.Add(item);

var filesToCleanup = Files.Select(f => f.ItemSpec).Where(f => !excludedAssemblies.Contains(Path.GetFileNameWithoutExtension(f), StringComparer.InvariantCultureIgnoreCase));

foreach (var item in filesToCleanup)
  File.Delete(item);
]]></Code>
    </Task>
  </UsingTask>
  <Target Name="CleanReferenceCopyLocalPaths" AfterTargets="AfterBuild;NonWinFodyTarget">
    <CosturaCleanup Config="FodyWeavers.xml" Files="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" />
  </Target>
  <Import Project="..\packages\TurboJpegWrapper.1.4.2.6\build\TurboJpegWrapper.targets" Condition="Exists('..\packages\TurboJpegWrapper.1.4.2.6\build\TurboJpegWrapper.targets')" />
  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
    <PropertyGroup>
      <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
    </PropertyGroup>
    <Error Condition="!Exists('..\packages\TurboJpegWrapper.1.4.2.6\build\TurboJpegWrapper.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\TurboJpegWrapper.1.4.2.6\build\TurboJpegWrapper.targets'))" />
  </Target>
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
</Project>
﻿#region

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using AgentInterface.Api.Models;
using AgentInterface.Api.ScreenShare;

#endregion

namespace AgentInterface.Api.Win32
{
    public class Display
    {
       
       
        [Flags]
        public enum ChangeDisplaySettingsFlags : uint
        {
            CDS_NONE = 0,
            CDS_UPDATEREGISTRY = 0x00000001,
            CDS_TEST = 0x00000002,
            CDS_FULLSCREEN = 0x00000004,
            CDS_GLOBAL = 0x00000008,
            CDS_SET_PRIMARY = 0x00000010,
            CDS_VIDEOPARAMETERS = 0x00000020,
            CDS_ENABLE_UNSAFE_MODES = 0x00000100,
            CDS_DISABLE_UNSAFE_MODES = 0x00000200,
            CDS_RESET = 0x40000000,
            CDS_RESET_EX = 0x20000000,
            CDS_NORESET = 0x10000000
        }

        [Flags]
        public enum DisplayDeviceStateFlags
        {
            /// <summary>The device is part of the desktop.</summary>
            AttachedToDesktop = 0x1,
            MultiDriver = 0x2,

            /// <summary>The device is part of the desktop.</summary>
            PrimaryDevice = 0x4,

            /// <summary>Represents a pseudo device used to mirror application drawing for remoting or other purposes.</summary>
            MirroringDriver = 0x8,

            /// <summary>The device is VGA compatible.</summary>
            VgaCompatible = 0x10,

            /// <summary>The device is removable; it cannot be the primary display.</summary>
            Removable = 0x20,

            /// <summary>The device has more display modes than its output devices support.</summary>
            ModesPruned = 0x8000000,
            Remote = 0x4000000,
            Disconnect = 0x2000000
        }

        public const int DMDO_DEFAULT = 0;
        public const int DMDO_90 = 1;
        public const int DMDO_180 = 2;
        public const int DMDO_270 = 3;

        public const int ErrorSuccess = 0;

        public const int ENUM_CURRENT_SETTINGS = -1;
        public const int CDS_UPDATEREGISTRY = 0x01;
        public const int CDS_TEST = 0x02;


        private const int ENUM_REGISTRY_SETTINGS = -2;

        public static int EnumCurrentSettings { get; } = -1;

        public static int EnumRegistrySettings { get; } = -2;

        private static string MonitorFriendlyName(Luid adapterId, uint targetId)
        {
            var deviceName = new DisplayconfigTargetDeviceName
            {
                header =
                {
                    size = (uint) Marshal.SizeOf(typeof(DisplayconfigTargetDeviceName)),
                    adapterId = adapterId,
                    id = targetId,
                    type = DisplayconfigDeviceInfoType.DisplayconfigDeviceInfoGetTargetName
                }
            };
            var error = DisplayConfigGetDeviceInfo(ref deviceName);
            if (error != ErrorSuccess)
                throw new Win32Exception(error);
            return deviceName.monitorFriendlyDeviceName;
        }

        private static IEnumerable<string> GetAllMonitorsFriendlyNames()
        {
            uint pathCount, modeCount;
            var error = GetDisplayConfigBufferSizes(QueryDeviceConfigFlags.QdcOnlyActivePaths, out pathCount,
                out modeCount);
            if (error != ErrorSuccess)
                throw new Win32Exception(error);

            var displayPaths = new DisplayconfigPathInfo[pathCount];
            var displayModes = new DisplayconfigModeInfo[modeCount];
            error = QueryDisplayConfig(QueryDeviceConfigFlags.QdcOnlyActivePaths,
                ref pathCount, displayPaths, ref modeCount, displayModes, IntPtr.Zero);
            if (error != ErrorSuccess)
                throw new Win32Exception(error);

            for (var i = 0; i < modeCount; i++)
                if (displayModes[i].infoType == DisplayconfigModeInfoType.DisplayconfigModeInfoTypeTarget)
                    yield return MonitorFriendlyName(displayModes[i].adapterId, displayModes[i].id);
        }

        public static List<string> DeviceFriendlyName()
        {
            return GetAllMonitorsFriendlyNames().ToList();
        }

        [DllImport("user32.dll")]
        public static extern int ChangeDisplaySettings(
            ref Devmode devMode, int flags);

        [DllImport("user32.dll")]
        public static extern DISP_CHANGE ChangeDisplaySettingsEx(string lpszDeviceName, ref Devmode lpDevMode,
            IntPtr hwnd, ChangeDisplaySettingsFlags dwflags, IntPtr lParam);

        [DllImport("user32.dll")]
        public static extern DISP_CHANGE ChangeDisplaySettingsEx(string lpszDeviceName, IntPtr lpDevMode, IntPtr hwnd,
            ChangeDisplaySettingsFlags dwflags, IntPtr lParam);

        [DllImport("user32.dll")]
        public static extern bool EnumDisplaySettings(
            string deviceName, int modeNum, ref Devmode devMode);

        private static List<DisplayInformation> UpdateDisplays()
        {
            var monitors = new List<DisplayInformation>();
            var d = new DisplayDevice();
            d.cb = Marshal.SizeOf(d);
            try
            {
                for (uint id = 0; EnumDisplayDevices(null, id, ref d, 0); id++)
                {
                    if (d.StateFlags.HasFlag(DisplayDeviceStateFlags.AttachedToDesktop))
                    {
                        var device = d.DeviceName;

                        var vDevMode = new Devmode();
                        var i = 0;
                        var supportedResolutions = new Dictionary<string, List<ResolutionInformation>>();
                        while (EnumDisplaySettings(device, i, ref vDevMode))
                        {
                            var width = vDevMode.dmPelsWidth;
                            var height = vDevMode.dmPelsHeight;
                            var bpp = vDevMode.dmBitsPerPel;
                            var orientation = vDevMode.dmDisplayOrientation.ToString();
                            var freq = vDevMode.dmDisplayFrequency;
                            var resolutionKey = $"{width}x{height}";
                            var resolution = new ResolutionInformation
                            {
                                BitsPerPixel = bpp,
                                Frequency = freq,
                                Height = height,
                                Width = width,
                                Orientation = orientation
                            };
                            if (supportedResolutions.ContainsKey(resolutionKey))
                            {
                                supportedResolutions[resolutionKey].Add(resolution);
                            }
                            else
                            {
                                supportedResolutions.Add(resolutionKey, new List<ResolutionInformation>());
                                supportedResolutions[resolutionKey].Add(resolution);
                            }
                            i++;
                        }
                        var cDevMode = new Devmode();
                        EnumDisplaySettings(device, ENUM_CURRENT_SETTINGS, ref cDevMode);

                        var currentResolution = new ResolutionInformation
                        {
                            BitsPerPixel = cDevMode.dmBitsPerPel,
                            Frequency = cDevMode.dmDisplayFrequency,
                            Height = cDevMode.dmPelsHeight,
                            Width = cDevMode.dmPelsWidth,
                            Orientation = cDevMode.dmDisplayOrientation.ToString(),
                            X = cDevMode.dmPositionX,
                            Y = cDevMode.dmPositionY
                        };
                        var monitor = new DisplayInformation
                        {
                            Primary = d.StateFlags.HasFlag(DisplayDeviceStateFlags.PrimaryDevice),
                            Attached = d.StateFlags.HasFlag(DisplayDeviceStateFlags.AttachedToDesktop),
                            Removable = d.StateFlags.HasFlag(DisplayDeviceStateFlags.Removable),
                            VgaCompatible = d.StateFlags.HasFlag(DisplayDeviceStateFlags.VgaCompatible),
                            MirroringDriver = d.StateFlags.HasFlag(DisplayDeviceStateFlags.MirroringDriver),
                            MultiDriver = d.StateFlags.HasFlag(DisplayDeviceStateFlags.MultiDriver),
                            ModesPruned = d.StateFlags.HasFlag(DisplayDeviceStateFlags.ModesPruned),
                            Remote = d.StateFlags.HasFlag(DisplayDeviceStateFlags.Remote),
                            Disconnect = d.StateFlags.HasFlag(DisplayDeviceStateFlags.Disconnect),
                            FriendlyName = $"{GetAllMonitorsFriendlyNames().ElementAt((int)id)} on {d.DeviceString}",
                            SupportedResolutions = supportedResolutions,
                            CurrentResolution = currentResolution,
                            DeviceName = device
                        };
                        monitors.Add(monitor);
                        d.cb = Marshal.SizeOf(d);
                        EnumDisplayDevices(d.DeviceName, 0, ref d, 0);
                    }
                    d.cb = Marshal.SizeOf(d);
                }
                return monitors;
            }
            catch
            {

            }
            string errorMessage = new Win32Exception(Marshal.GetLastWin32Error()).Message;
            Console.WriteLine(errorMessage);
            return monitors;
        }

        public static List<DisplayInformation> DisplayInformation()
        { 
            return UpdateDisplays();
        }

        public static string SetPrimary(string deviceName)
        {
            var id = int.Parse(Regex.Match(deviceName, @"\d+").Value) - 1;
            var originalMode = new Devmode();
            originalMode.dmSize = (short) Marshal.SizeOf(originalMode);
            EnumDisplaySettings(deviceName, ENUM_CURRENT_SETTINGS, ref originalMode);
            var offsetx = originalMode.dmPositionX;
            var offsety = originalMode.dmPositionY;
            originalMode.dmPositionX = 0;
            originalMode.dmPositionY = 0;

            ChangeDisplaySettingsEx(deviceName, ref originalMode, (IntPtr) null,
                ChangeDisplaySettingsFlags.CDS_SET_PRIMARY | ChangeDisplaySettingsFlags.CDS_UPDATEREGISTRY |
                ChangeDisplaySettingsFlags.CDS_NORESET, IntPtr.Zero);
            var device = new DisplayDevice();
            device.cb = Marshal.SizeOf(device);

            // Update remaining devices
            for (uint otherid = 0; EnumDisplayDevices(null, otherid, ref device, 0); otherid++)
            {
                if (device.StateFlags.HasFlag(DisplayDeviceStateFlags.AttachedToDesktop) && otherid != id)
                {
                    device.cb = Marshal.SizeOf(device);
                    var otherDeviceMode = new Devmode();

                    EnumDisplaySettings(device.DeviceName, -1, ref otherDeviceMode);

                    otherDeviceMode.dmPositionX -= offsetx;
                    otherDeviceMode.dmPositionY -= offsety;

                    ChangeDisplaySettingsEx(
                        device.DeviceName,
                        ref otherDeviceMode,
                        (IntPtr) null,
                        ChangeDisplaySettingsFlags.CDS_UPDATEREGISTRY | ChangeDisplaySettingsFlags.CDS_NORESET,
                        IntPtr.Zero);
                }

                device.cb = Marshal.SizeOf(device);
            }

            // Apply settings
            return
                GetMessageForCode(ChangeDisplaySettingsEx(null, IntPtr.Zero, (IntPtr) null,
                    ChangeDisplaySettingsFlags.CDS_NONE, (IntPtr) null));
        }
        [DllImport("kernel32.dll")]
        public static extern uint GetLastError();

        public static string Rotate(int angle, int width, int height, string deviceName)
        {
            var originalMode = new Devmode();
            originalMode.dmSize = (short) Marshal.SizeOf(originalMode);
            EnumDisplaySettings(deviceName, ENUM_CURRENT_SETTINGS, ref originalMode);

            // swap height and width
            var temp = originalMode.dmPelsHeight;
            originalMode.dmPelsHeight = originalMode.dmPelsWidth;
            originalMode.dmPelsWidth = temp;

            originalMode.dmPelsWidth = width;
            originalMode.dmPelsHeight = height;
            switch (angle)
            {
                case 0:
                    originalMode.dmDisplayOrientation = ScreenOrientation.Angle0;
                    break;
                case 90:
                    originalMode.dmDisplayOrientation = ScreenOrientation.Angle90;
                    break;
                case 180:
                    originalMode.dmDisplayOrientation = ScreenOrientation.Angle180;
                    break;
                case 270:
                    originalMode.dmDisplayOrientation = ScreenOrientation.Angle270;
                    break;
            }
            return GetMessageForCode(ChangeDisplaySettingsEx(deviceName, ref originalMode, IntPtr.Zero,
                ChangeDisplaySettingsFlags.CDS_UPDATEREGISTRY, IntPtr.Zero));
        }

        public static string ChangeResolution(string deviceName, int width, int height, int bbp, int freq)
        {
            var originalMode = new Devmode();
            originalMode.dmSize = (short) Marshal.SizeOf(originalMode);
            EnumDisplaySettings(deviceName, ENUM_CURRENT_SETTINGS, ref originalMode);
            var newMode = originalMode;
            newMode.dmDeviceName = deviceName;
            newMode.dmPelsWidth = width;
            newMode.dmPelsHeight = height;
            newMode.dmBitsPerPel = bbp;
            newMode.dmDisplayFrequency = freq;
            return GetMessageForCode(ChangeDisplaySettingsEx(deviceName, ref newMode, IntPtr.Zero,
                ChangeDisplaySettingsFlags.CDS_UPDATEREGISTRY, IntPtr.Zero));
        }

        private static string GetMessageForCode(DISP_CHANGE code)
        {
            string message;
            switch (code)
            {
                case DISP_CHANGE.Successful:
                    message = "Resolution updated.";
                    break;
                case DISP_CHANGE.Restart:
                    message = "A restart is required for this resolution to take effect.";
                    break;
                case DISP_CHANGE.BadMode:
                    message = $"resolution is not valid.";
                    break;
                case DISP_CHANGE.BadDualView:
                    message = "The settings change was unsuccessful because system is DualView capable.";
                    break;
                case DISP_CHANGE.BadFlags:
                    message = "An invalid set of flags was passed in.";
                    break;
                case DISP_CHANGE.BadParam:
                    message =
                        "An invalid parameter was passed in. This can include an invalid flag or combination of flags.";
                    break;
                case DISP_CHANGE.Failed:
                    message = "Resolution failed to update.";
                    break;
                case DISP_CHANGE.NotUpdated:
                    message = "Unable to write settings to the registry.";
                    break;
                default:
                    message = "Unknown return value from ChangeDisplaySettings API.";
                    break;
            }
            return message;
        }

        [DllImport("user32.dll")]
        private static extern bool EnumDisplayDevices(string lpDevice, uint iDevNum, ref DisplayDevice lpDisplayDevice,
            uint dwFlags);

        public enum DISP_CHANGE
        {
            Successful = 0,
            Restart = 1,
            Failed = -1,
            BadMode = -2,
            NotUpdated = -3,
            BadFlags = -4,
            BadParam = -5,
            BadDualView = -6
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct Devmode
        {
            private const int Cchdevicename = 0x20;
            private const int Cchformname = 0x20;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)] public string dmDeviceName;
            public short dmSpecVersion;
            public short dmDriverVersion;
            public short dmSize;
            public short dmDriverExtra;
            public int dmFields;
            public int dmPositionX;
            public int dmPositionY;
            public ScreenOrientation dmDisplayOrientation;
            public int dmDisplayFixedOutput;
            public short dmColor;
            public short dmDuplex;
            public short dmYResolution;
            public short dmTTOption;
            public short dmCollate;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)] public string dmFormName;
            public short dmLogPixels;
            public int dmBitsPerPel;
            public int dmPelsWidth;
            public int dmPelsHeight;
            public int dmDisplayFlags;
            public int dmDisplayFrequency;
            public int dmICMMethod;
            public int dmICMIntent;
            public int dmMediaType;
            public int dmDitherType;
            public int dmReserved1;
            public int dmReserved2;
            public int dmPanningWidth;
            public int dmPanningHeight;
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public struct DisplayDevice
        {
            [MarshalAs(UnmanagedType.U4)] public int cb;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string DeviceName;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string DeviceString;
            [MarshalAs(UnmanagedType.U4)] public DisplayDeviceStateFlags StateFlags;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string DeviceID;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string DeviceKey;
        }

        #region enums

        public enum QueryDeviceConfigFlags : uint
        {
            QdcAllPaths = 0x00000001,
            QdcOnlyActivePaths = 0x00000002,
            QdcDatabaseCurrent = 0x00000004
        }

        public enum DisplayconfigVideoOutputTechnology : uint
        {
            DisplayconfigOutputTechnologyOther = 0xFFFFFFFF,
            DisplayconfigOutputTechnologyHd15 = 0,
            DisplayconfigOutputTechnologySvideo = 1,
            DisplayconfigOutputTechnologyCompositeVideo = 2,
            DisplayconfigOutputTechnologyComponentVideo = 3,
            DisplayconfigOutputTechnologyDvi = 4,
            DisplayconfigOutputTechnologyHdmi = 5,
            DisplayconfigOutputTechnologyLvds = 6,
            DisplayconfigOutputTechnologyDJpn = 8,
            DisplayconfigOutputTechnologySdi = 9,
            DisplayconfigOutputTechnologyDisplayportExternal = 10,
            DisplayconfigOutputTechnologyDisplayportEmbedded = 11,
            DisplayconfigOutputTechnologyUdiExternal = 12,
            DisplayconfigOutputTechnologyUdiEmbedded = 13,
            DisplayconfigOutputTechnologySdtvdongle = 14,
            DisplayconfigOutputTechnologyMiracast = 15,
            DisplayconfigOutputTechnologyInternal = 0x80000000,
            DisplayconfigOutputTechnologyForceUint32 = 0xFFFFFFFF
        }

        public enum DisplayconfigScanlineOrdering : uint
        {
            DisplayconfigScanlineOrderingUnspecified = 0,
            DisplayconfigScanlineOrderingProgressive = 1,
            DisplayconfigScanlineOrderingInterlaced = 2,
            DisplayconfigScanlineOrderingInterlacedUpperfieldfirst = DisplayconfigScanlineOrderingInterlaced,
            DisplayconfigScanlineOrderingInterlacedLowerfieldfirst = 3,
            DisplayconfigScanlineOrderingForceUint32 = 0xFFFFFFFF
        }

        public enum DisplayconfigRotation : uint
        {
            DisplayconfigRotationIdentity = 1,
            DisplayconfigRotationRotate90 = 2,
            DisplayconfigRotationRotate180 = 3,
            DisplayconfigRotationRotate270 = 4,
            DisplayconfigRotationForceUint32 = 0xFFFFFFFF
        }

        public enum DisplayconfigScaling : uint
        {
            DisplayconfigScalingIdentity = 1,
            DisplayconfigScalingCentered = 2,
            DisplayconfigScalingStretched = 3,
            DisplayconfigScalingAspectratiocenteredmax = 4,
            DisplayconfigScalingCustom = 5,
            DisplayconfigScalingPreferred = 128,
            DisplayconfigScalingForceUint32 = 0xFFFFFFFF
        }
        [DllImport("user32")]
        private static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lpRect, MonitorEnumProc callback, int dwData);

        private delegate bool MonitorEnumProc(IntPtr hDesktop, IntPtr hdc, ref Rect pRect, int dwData);

        [StructLayout(LayoutKind.Sequential)]
        private struct Rect
        {
            public int left;
            public int top;
            public int right;
            public int bottom;
        }

        public enum DisplayconfigPixelformat : uint
        {
            DisplayconfigPixelformat8Bpp = 1,
            DisplayconfigPixelformat16Bpp = 2,
            DisplayconfigPixelformat24Bpp = 3,
            DisplayconfigPixelformat32Bpp = 4,
            DisplayconfigPixelformatNongdi = 5,
            DisplayconfigPixelformatForceUint32 = 0xffffffff
        }

        public enum DisplayconfigModeInfoType : uint
        {
            DisplayconfigModeInfoTypeSource = 1,
            DisplayconfigModeInfoTypeTarget = 2,
            DisplayconfigModeInfoTypeForceUint32 = 0xFFFFFFFF
        }

        public enum DisplayconfigDeviceInfoType : uint
        {
            DisplayconfigDeviceInfoGetSourceName = 1,
            DisplayconfigDeviceInfoGetTargetName = 2,
            DisplayconfigDeviceInfoGetTargetPreferredMode = 3,
            DisplayconfigDeviceInfoGetAdapterName = 4,
            DisplayconfigDeviceInfoSetTargetPersistence = 5,
            DisplayconfigDeviceInfoGetTargetBaseType = 6,
            DisplayconfigDeviceInfoForceUint32 = 0xFFFFFFFF
        }

        #endregion

        #region structs

        [StructLayout(LayoutKind.Sequential)]
        public struct Luid
        {
            public uint LowPart;
            public int HighPart;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct DisplayconfigPathSourceInfo
        {
            public Luid adapterId;
            public uint id;
            public uint modeInfoIdx;
            public uint statusFlags;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct DisplayconfigPathTargetInfo
        {
            public Luid adapterId;
            public uint id;
            public uint modeInfoIdx;
            private readonly DisplayconfigVideoOutputTechnology outputTechnology;
            private readonly DisplayconfigRotation rotation;
            private readonly DisplayconfigScaling scaling;
            private readonly DisplayconfigRational refreshRate;
            private readonly DisplayconfigScanlineOrdering scanLineOrdering;
            public bool targetAvailable;
            public uint statusFlags;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct DisplayconfigRational
        {
            public uint Numerator;
            public uint Denominator;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct DisplayconfigPathInfo
        {
            public DisplayconfigPathSourceInfo sourceInfo;
            public DisplayconfigPathTargetInfo targetInfo;
            public uint flags;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct Displayconfig2Dregion
        {
            public uint cx;
            public uint cy;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct DisplayconfigVideoSignalInfo
        {
            public ulong pixelRate;
            public DisplayconfigRational hSyncFreq;
            public DisplayconfigRational vSyncFreq;
            public Displayconfig2Dregion activeSize;
            public Displayconfig2Dregion totalSize;
            public uint videoStandard;
            public DisplayconfigScanlineOrdering scanLineOrdering;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct DisplayconfigTargetMode
        {
            public DisplayconfigVideoSignalInfo targetVideoSignalInfo;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct Pointl
        {
            private readonly int x;
            private readonly int y;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct DisplayconfigSourceMode
        {
            public uint width;
            public uint height;
            public DisplayconfigPixelformat pixelFormat;
            public Pointl position;
        }

        [StructLayout(LayoutKind.Explicit)]
        public struct DisplayconfigModeInfoUnion
        {
            [FieldOffset(0)] public DisplayconfigTargetMode targetMode;

            [FieldOffset(0)] public DisplayconfigSourceMode sourceMode;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct DisplayconfigModeInfo
        {
            public DisplayconfigModeInfoType infoType;
            public uint id;
            public Luid adapterId;
            public DisplayconfigModeInfoUnion modeInfo;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct DisplayconfigTargetDeviceNameFlags
        {
            public uint value;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct DisplayconfigDeviceInfoHeader
        {
            public DisplayconfigDeviceInfoType type;
            public uint size;
            public Luid adapterId;
            public uint id;
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        public struct DisplayconfigTargetDeviceName
        {
            public DisplayconfigDeviceInfoHeader header;
            public DisplayconfigTargetDeviceNameFlags flags;
            public DisplayconfigVideoOutputTechnology outputTechnology;
            public ushort edidManufactureId;
            public ushort edidProductCodeId;
            public uint connectorInstance;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string monitorFriendlyDeviceName;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string monitorDevicePath;
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int Left, Top, Right, Bottom;

            public RECT(int left, int top, int right, int bottom)
            {
                Left = left;
                Top = top;
                Right = right;
                Bottom = bottom;
            }

            public RECT(Rectangle r) : this(r.Left, r.Top, r.Right, r.Bottom) { }

            public int X
            {
                get { return Left; }
                set { Right -= (Left - value); Left = value; }
            }

            public int Y
            {
                get { return Top; }
                set { Bottom -= (Top - value); Top = value; }
            }

            public int Height
            {
                get { return Bottom - Top; }
                set { Bottom = value + Top; }
            }

            public int Width
            {
                get { return Right - Left; }
                set { Right = value + Left; }
            }

            

            public Size Size
            {
                get { return new Size(Width, Height); }
                set { Width = value.Width; Height = value.Height; }
            }

            public static implicit operator Rectangle(RECT r)
            {
                return new Rectangle(r.Left, r.Top, r.Width, r.Height);
            }

            public static implicit operator RECT(Rectangle r)
            {
                return new RECT(r);
            }

            public static bool operator ==(RECT r1, RECT r2)
            {
                return r1.Equals(r2);
            }

            public static bool operator !=(RECT r1, RECT r2)
            {
                return !r1.Equals(r2);
            }

            public bool Equals(RECT r)
            {
                return r.Left == Left && r.Top == Top && r.Right == Right && r.Bottom == Bottom;
            }

            public override bool Equals(object obj)
            {
                if (obj is RECT)
                    return Equals((RECT)obj);
                else if (obj is Rectangle)
                    return Equals(new RECT((Rectangle)obj));
                return false;
            }

            public override int GetHashCode()
            {
                return ((Rectangle)this).GetHashCode();
            }

            public override string ToString()
            {
                return string.Format(CultureInfo.CurrentCulture, "{{Left={0},Top={1},Right={2},Bottom={3}}}", Left, Top, Right, Bottom);
            }
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct CURSORINFO
        {
            public Int32 cbSize;        // Specifies the size, in bytes, of the structure. 
            public Int32 flags;         // Specifies the cursor state. This parameter can be one of the following values:
            public IntPtr hCursor;          // Handle to the cursor. 
            public POINT ptScreenPos;       // A POINT structure that receives the screen coordinates of the cursor. 
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct ICONINFO
        {
            public bool fIcon;         // Specifies whether this structure defines an icon or a cursor. A value of TRUE specifies 
            public Int32 xHotspot;     // Specifies the x-coordinate of a cursor's hot spot. If this structure defines an icon, the hot 
            public Int32 yHotspot;     // Specifies the y-coordinate of the cursor's hot spot. If this structure defines an icon, the hot 
            public IntPtr hbmMask;     // (HBITMAP) Specifies the icon bitmask bitmap. If this structure defines a black and white icon, 
            public IntPtr hbmColor;    // (HBITMAP) Handle to the icon color bitmap. This member can be optional if this 
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct POINT
        {
            public Int32 x;
            public Int32 y;
        }
        public const int Width = 0;
        public const int Height = 1;
        public struct ScreenSize
        {
            public int Width;
            public int Height;
        }
        public const Int32 CURSOR_SHOWING = 0x00000001;

        [DllImport("user32.dll", EntryPoint = "GetDesktopWindow")]
        public static extern IntPtr GetDesktopWindow();

        [DllImport("user32.dll", EntryPoint = "GetDC")]
        public static extern IntPtr GetDesktopContext(IntPtr ptr);

        [DllImport("user32.dll", EntryPoint = "GetSystemMetrics")]
        public static extern int GetSystemMetrics(int abc);

        [DllImport("user32.dll", EntryPoint = "GetWindowDC")]
        public static extern IntPtr GetWindowDesktopContext(Int32 ptr);

        [DllImport("user32.dll", EntryPoint = "ReleaseDC")]
        public static extern IntPtr ReleaseDesktopContext(IntPtr hWnd, IntPtr hDc);

        [DllImport("user32.dll", EntryPoint = "GetCursorInfo")]
        public static extern bool GetCursorInfo(out CursorInfo pci);

        [DllImport("user32.dll", EntryPoint = "CopyIcon")]
        public static extern IntPtr CopyIcon(IntPtr hIcon);

        [DllImport("user32.dll", EntryPoint = "GetIconInfo")]
        public static extern bool GetIconInfo(IntPtr hIcon, out IconInfo piconinfo);

        [DllImport("user32.dll", EntryPoint = "DestroyIcon")]
        public static extern bool DestroyIcon(IntPtr hIcon);
        #endregion
        [StructLayout(LayoutKind.Sequential)]
        public struct IconInfo
        {
            public bool IsIcon;         // Specifies whether this structure defines an icon or a cursor. A value of TRUE specifies 
            public Int32 Xcoord;     // Specifies the x-coordinate of a cursor's hot spot. If this structure defines an icon, the hot 
            public Int32 Ycoord;     // Specifies the y-coordinate of the cursor's hot spot. If this structure defines an icon, the hot 
            public IntPtr Bitmask;     // (HBITMAP) Specifies the icon bitmask bitmap. If this structure defines a black and white icon, 
            public IntPtr Color;    // (HBITMAP) Handle to the icon color bitmap. This member can be optional if this 
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct Point
        {
            public Int32 X;
            public Int32 Y;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct CursorInfo
        {
            public Int32 Size;        // Specifies the size, in bytes, of the structure. 
            public Int32 State;         // Specifies the cursor state. This parameter can be one of the following values:
            public IntPtr Handle;          // Handle to the cursor. 
            public Point Coordinates;       // A POINT structure that receives the screen coordinates of the cursor. 
        }

        #region DLL-Imports

        [DllImport("user32.dll")]
        public static extern int GetDisplayConfigBufferSizes(
            QueryDeviceConfigFlags flags, out uint numPathArrayElements, out uint numModeInfoArrayElements);

        [DllImport("user32.dll")]
        public static extern int QueryDisplayConfig(
            QueryDeviceConfigFlags flags,
            ref uint numPathArrayElements, [Out] DisplayconfigPathInfo[] pathInfoArray,
            ref uint numModeInfoArrayElements, [Out] DisplayconfigModeInfo[] modeInfoArray,
            IntPtr currentTopologyId
            );

        [DllImport("user32.dll")]
        public static extern int DisplayConfigGetDeviceInfo(ref DisplayconfigTargetDeviceName deviceName);

      
        [DllImport("user32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
       public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);

       public static Rectangle GetWindowRectangle()
        {
            RECT scBounds = new RECT();
            GetWindowRect(GetDesktopWindow(), ref scBounds);
            return scBounds;
        }

        public const int SRCCOPY = 13369376;

        [DllImport("gdi32.dll", EntryPoint = "CreateDC")]
        public static extern IntPtr CreateDesktopContext(IntPtr lpszDriver, string lpszDevice, IntPtr lpszOutput, IntPtr lpInitData);

        [DllImport("gdi32.dll", EntryPoint = "DeleteDC")]
        public static extern IntPtr DeleteDesktopContext(IntPtr hDc);

        [DllImport("gdi32.dll", EntryPoint = "DeleteObject")]
        public static extern IntPtr DeleteObject(IntPtr hDc);

        [DllImport("gdi32.dll", EntryPoint = "BitBlt")]
        public static extern bool BitBlt(IntPtr hdcDest, int xDest,
                                         int yDest, int wDest,
                                         int hDest, IntPtr hdcSource,
                                         int xSrc, int ySrc, int rasterOp);

        [DllImport("gdi32.dll", EntryPoint = "CreateCompatibleBitmap")]
        public static extern IntPtr CreateCompatibleBitmap
                                    (IntPtr hdc, int nWidth, int nHeight);

        [DllImport("gdi32.dll", EntryPoint = "CreateCompatibleDC")]
        public static extern IntPtr CreateCompatibleDesktopContext(IntPtr hdc);

        [DllImport("gdi32.dll", EntryPoint = "SelectObject")]
        public static extern IntPtr SelectObject(IntPtr hdc, IntPtr bmp);

        #endregion
    }

    
}
﻿#region

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Principal;
using Cassia;

#endregion

namespace AgentInterface.Api.Win32
{
    /// <summary>
    ///     Class that allows running applications with full admin rights. In
    ///     addition the application launched will bypass the Vista UAC prompt.
    /// </summary>
    public class ProcessStarter
    {



        private static int GetUserSessionId(string username)
        {
            try
            {
                ITerminalServicesManager manager = new TerminalServicesManager();
                using (ITerminalServer server = manager.GetLocalServer())
                {
                    server.Open();
                    foreach (ITerminalServicesSession session in server.GetSessions())
                    {

                        NTAccount account = session.UserAccount;
                        if (account == null) continue;
                        var userName = account.Value.Split('\\')[1];
                        if (userName.ToLower().Equals(username.ToLower())) return session.SessionId;
                    }
                }
                return -1;
            }
            catch (Exception)
            {

                return -1;
            }
        }


        /// <summary>
        ///     Launches the given application with full admin rights, and in addition bypasses the Vista UAC prompt
        /// </summary>
        /// <param name="applicationName">The name of the application to launch</param>
        /// <param name="procInfo">Process information regarding the launched application that gets returned to the caller</param>
        /// <returns></returns>
        public static bool  StartProcessAndBypassUAC(string applicationName, out PROCESS_INFORMATION procInfo)
        {
            uint winlogonPid = 0;
            IntPtr hUserTokenDup = IntPtr.Zero, hPToken = IntPtr.Zero, hProcess = IntPtr.Zero;
            procInfo = new PROCESS_INFORMATION();


            // obtain the currently active session id; every logged on user in the system has a unique session id
            var dwSessionId = -1;

                dwSessionId = (int) WTSGetActiveConsoleSessionId();
            
            // obtain the process id of the winlogon process that is running within the currently active session
            var processes = Process.GetProcessesByName("winlogon");
            foreach (var p in processes)
            {
                if ((uint) p.SessionId == dwSessionId)
                {
                    winlogonPid = (uint) p.Id;
                }
            }

            // obtain a handle to the winlogon process
            hProcess = OpenProcess(MAXIMUM_ALLOWED, false, winlogonPid);

            // obtain a handle to the access token of the winlogon process
            if (!OpenProcessToken(hProcess, TOKEN_DUPLICATE, ref hPToken))
            {
                CloseHandle(hProcess);
                return false;
            }

            // Security attibute structure used in DuplicateTokenEx and CreateProcessAsUser
            // I would prefer to not have to use a security attribute variable and to just 
            // simply pass null and inherit (by default) the security attributes
            // of the existing token. However, in C# structures are value types and therefore
            // cannot be assigned the null value.
            var sa = new SECURITY_ATTRIBUTES();
            sa.Length = Marshal.SizeOf(sa);

            // copy the access token of the winlogon process; the newly created token will be a primary token
            if (
                !DuplicateTokenEx(hPToken, MAXIMUM_ALLOWED, ref sa,
                    (int) SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, (int) TOKEN_TYPE.TokenPrimary,
                    ref hUserTokenDup))
            {
                CloseHandle(hProcess);
                CloseHandle(hPToken);
                return false;
            }

            // By default CreateProcessAsUser creates a process on a non-interactive window station, meaning
            // the window station has a desktop that is invisible and the process is incapable of receiving
            // user input. To remedy this we set the lpDesktop parameter to indicate we want to enable user 
            // interaction with the new process.
            var si = new STARTUPINFO();
            si.cb = Marshal.SizeOf(si);
            si.lpDesktop = @"winsta0\default";
                // interactive window station parameter; basically this indicates that the process created can display a GUI on the desktop

            // flags that specify the priority and creation method of the process
            var dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;

            // create a new process in the current user's logon session
            var result = CreateProcessAsUser(hUserTokenDup, // client's access token
                null, // file to execute
                applicationName, // command line
                ref sa, // pointer to process SECURITY_ATTRIBUTES
                ref sa, // pointer to thread SECURITY_ATTRIBUTES
                false, // handles are not inheritable
                dwCreationFlags, // creation flags
                IntPtr.Zero, // pointer to new environment block 
                null, // name of current directory 
                ref si, // pointer to STARTUPINFO structure
                out procInfo // receives information about new process
                );

            // invalidate the handles
            CloseHandle(hProcess);
            CloseHandle(hPToken);
            CloseHandle(hUserTokenDup);

            return result; // return the result
        }

        #region Structures

        [StructLayout(LayoutKind.Sequential)]
        public struct SECURITY_ATTRIBUTES
        {
            public int Length;
            public IntPtr lpSecurityDescriptor;
            public bool bInheritHandle;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct STARTUPINFO
        {
            public int cb;
            public string lpReserved;
            public string lpDesktop;
            public string lpTitle;
            public uint dwX;
            public uint dwY;
            public uint dwXSize;
            public uint dwYSize;
            public uint dwXCountChars;
            public uint dwYCountChars;
            public uint dwFillAttribute;
            public uint dwFlags;
            public short wShowWindow;
            public short cbReserved2;
            public IntPtr lpReserved2;
            public IntPtr hStdInput;
            public IntPtr hStdOutput;
            public IntPtr hStdError;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct PROCESS_INFORMATION
        {
            public IntPtr hProcess;
            public IntPtr hThread;
            public uint dwProcessId;
            public uint dwThreadId;
        }

        #endregion

        #region Enumerations

        private enum TOKEN_TYPE
        {
            TokenPrimary = 1,
            TokenImpersonation = 2
        }

        private enum SECURITY_IMPERSONATION_LEVEL
        {
            SecurityAnonymous = 0,
            SecurityIdentification = 1,
            SecurityImpersonation = 2,
            SecurityDelegation = 3
        }

        #endregion

        #region Constants

        public const int TOKEN_DUPLICATE = 0x0002;
        public const uint MAXIMUM_ALLOWED = 0x2000000;
        public const int CREATE_NEW_CONSOLE = 0x00000010;

        public const int IDLE_PRIORITY_CLASS = 0x40;
        public const int NORMAL_PRIORITY_CLASS = 0x20;
        public const int HIGH_PRIORITY_CLASS = 0x80;
        public const int REALTIME_PRIORITY_CLASS = 0x100;

        #endregion

        #region Win32 API Imports

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool CloseHandle(IntPtr hSnapshot);

        [DllImport("kernel32.dll")]
        private static extern uint WTSGetActiveConsoleSessionId();

        [DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUser", SetLastError = true, CharSet = CharSet.Ansi,
            CallingConvention = CallingConvention.StdCall)]
        public static extern bool CreateProcessAsUser(IntPtr hToken, string lpApplicationName, string lpCommandLine,
            ref SECURITY_ATTRIBUTES lpProcessAttributes,
            ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandle, int dwCreationFlags, IntPtr lpEnvironment,
            string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);

        [DllImport("kernel32.dll")]
        private static extern bool ProcessIdToSessionId(uint dwProcessId, ref uint pSessionId);

        [DllImport("advapi32.dll", EntryPoint = "DuplicateTokenEx")]
        public static extern bool DuplicateTokenEx(IntPtr ExistingTokenHandle, uint dwDesiredAccess,
            ref SECURITY_ATTRIBUTES lpThreadAttributes, int TokenType,
            int ImpersonationLevel, ref IntPtr DuplicateTokenHandle);

        [DllImport("kernel32.dll")]
        private static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId);

        [DllImport("advapi32", SetLastError = true), SuppressUnmanagedCodeSecurity]
        private static extern bool OpenProcessToken(IntPtr ProcessHandle, int DesiredAccess, ref IntPtr TokenHandle);

        #endregion
    }
}
﻿<?xml version="1.0" encoding="utf-8"?>
<Weavers>
  
</Weavers>
﻿using System.ServiceModel;
using AgentInterface.Api.Models;

namespace AgentInterface
{
    [ServiceContract(Namespace = "https://ulterius.io/")]
    public interface IFrameContract
    {

        [OperationContract]
        FrameInformation GetCleanFrame();

        [OperationContract]
        FrameInformation GetFullFrame();

        [OperationContract]
        bool KeepAlive();

    }
}
﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
using AgentInterface.Api.Models;

namespace AgentInterface
{
    [ServiceContract(Namespace = "https://ulterius.io/")]
    public interface IInputContract
    {

        [OperationContract(IsOneWay = true)]
        void HandleRightMouseDown();

        [OperationContract(IsOneWay = true)]
        void HandleRightMouseUp();

        [OperationContract(IsOneWay = true)]
        void MoveMouse(int x, int y);

        [OperationContract(IsOneWay = true)]
        void MouseScroll(bool positive);

        [OperationContract(IsOneWay = true)]
        void HandleLeftMouseDown();

        [OperationContract(IsOneWay = true)]
        void HandleLeftMouseUp();

        [OperationContract(IsOneWay = true)]
        void HandleKeyDown(List<int> keyCodes);

        [OperationContract(IsOneWay = true)]
        void HandleKeyUp(List<int> keyCodes);

        [OperationContract(IsOneWay = true)]
        void HandleRightClick();

        [OperationContract]
        float GetGpuTemp(string gpuName);

        [OperationContract]
        List<DisplayInformation> GetDisplayInformation();

        [OperationContract]
        List<float> GetCpuTemps();

    }
}
﻿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("AgentInterface")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Octopodal Solutions")]
[assembly: AssemblyProduct("Ulterius")]
[assembly: AssemblyCopyright("Copyright ©  2016")]
[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("5c3b0b17-cbb7-4b4b-b527-1fab2bb96466")]

// 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")]
﻿<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Cassia" version="2.0.0.60" targetFramework="net452" />
  <package id="Newtonsoft.Json" version="10.0.1-beta1" targetFramework="net452" />
  <package id="OpenHardwareMonitor" version="0.7.1" targetFramework="net452" />
  <package id="SharpDX" version="3.1.1" targetFramework="net452" />
  <package id="SharpDX.Direct3D11" version="3.1.1" targetFramework="net452" />
  <package id="SharpDX.DXGI" version="3.1.1" targetFramework="net452" />
  <package id="SharpDX.Mathematics" version="3.1.1" targetFramework="net452" />
  <package id="TurboJpegWrapper" version="1.4.2.6" targetFramework="net452" />
</packages>
                                var targetPort = _client.LocalEndpoint.Port;
                    var targetPort = _client.LocalEndpoint.Port;
                    var targetPort = _client.LocalEndpoint.Port;
using AgentInterface.Api.Models;
using AgentInterface.Settings;
using AgentInterface.Api.Win32;
            var device = _packet.Args[0].ToString();
            _builder.WriteMessage(formThread);
            var width = int.Parse(_packet.Args[0].ToString());
            _builder.WriteMessage(formThread);
            var width = int.Parse(_packet.Args[0].ToString());
            _builder.WriteMessage(formThread);
using AgentInterface.Settings;
using AgentInterface.Api.System;
            return UlteriusApiServer.RunningAsService
                ? UlteriusApiServer.AgentClient.GetGpuTemp(gpuName)
                : SystemData.GetGpuTemp(gpuName);
using AgentInterface.Api.Win32;
                if (Environment.UserName.Equals("SYSTEM") && Tools.RunningPlatform() == Tools.Platform.Windows)
                {
                    var task = Task.Run(() =>
                    {
                        try
                        {
                            ProcessStarter.PROCESS_INFORMATION procInfo;
                            ProcessStarter.StartProcessAndBypassUAC(path,  out procInfo);
                        }
                        catch (Exception)
                        {
                            //continue
                        }
                    });
                    processStarted = task.Wait(TimeSpan.FromSeconds(5));
                }
                else
                {
                    var processStartInfo = new ProcessStartInfo(path);
                    var process = new Process {StartInfo = processStartInfo};
                    processStarted = process.Start();
                    processId = process.Id;
                }
using AgentInterface.Api.ScreenShare;
using AgentInterface.Api.ScreenShare.DesktopDuplication;
using AgentInterface.Api.Win32;
                var stream = RunningAsService
                    ? new Thread(GetScreenAgentFrame) { IsBackground = true }
                    : new Thread(GetScreenFrame) { IsBackground = true };

        private void GetScreenAgentFrame()
        {
            try
            {
                while (_client != null && _client.IsConnected && _authClient != null &&
                       !_authClient.ShutDownScreenShare)
                {
                    try
                    {
                        var image = AgentClient.GetCleanFrame();
                        if (image != null)
                        {
                            if (image.UsingGpu)
                            {
                                SendGpuFrame(image.FinishedRegions);
                            }
                            else
                            {
                                SendPolledFrame(image.ScreenImage, image.Bounds);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        //  Console.WriteLine(e.Message + " " + e.StackTrace);
                    }
                }
                Console.WriteLine("Screen Share Died");
            }
            catch (Exception)
            {
            }
        }

                    if (RunningAsService)
                    {
                        HandleAgentFullFrame();
                    }
                    else
                    {
                        HandleFullFrame();
                    }
            if (!ScreenShareService.Streams.ContainsKey(_authClient)) return;
            if (RunningAsService)
            {
                AgentClient.HandleRightMouseUp();
            }
            else
            {
                new InputSimulator().Mouse.RightButtonUp();
            }
            if (!ScreenShareService.Streams.ContainsKey(_authClient)) return;
            if (RunningAsService)
            {
                AgentClient.HandleRightMouseDown();
            }
            else
            {
                new InputSimulator().Mouse.RightButtonDown();
            }
        }

        private void HandleAgentFullFrame()
        {
            try
            {
                var fullFrameData = AgentClient.GetFullFrame();
                if (fullFrameData?.ScreenImage == null) throw new InvalidOperationException("Frame was null");
                var bounds = fullFrameData.Bounds;
                var image = ScreenData.ImageToByteArray(fullFrameData.ScreenImage);
                var frameData = new
                {
                    screenBounds = new
                    {
                        top = bounds.Top,
                        bottom = bounds.Bottom,
                        left = bounds.Left,
                        right = bounds.Right,
                        height = bounds.Height,
                        width = bounds.Width,
                        x = bounds.X,
                        y = bounds.Y,
                        empty = bounds.IsEmpty,
                        location = bounds.Location,
                        size = bounds.Size
                    },
                    frameData = image.Select(b => (int)b).ToArray()
                };
                _builder.WriteMessage(frameData);
            }
            catch (Exception ex)
            {
                var data = new
                {
                    frameFailed = true,
                    message = ex.Message
                };
                Console.WriteLine(ex.Message + "Fuck");
                _builder.WriteMessage(data);
            }
            if (!ScreenShareService.Streams.ContainsKey(_authClient)) return;
            if (RunningAsService)
            {
                AgentClient.HandleKeyUp(codes);
            }
            else
                foreach (var code in codes)
                {
                    var virtualKey = (VirtualKeyCode)code;
                    new InputSimulator().Keyboard.KeyUp(virtualKey);
                }
            if (!ScreenShareService.Streams.ContainsKey(_authClient)) return;
            if (RunningAsService)
                AgentClient.HandleKeyDown(codes);
            }
            else
            {
                foreach (var code in codes)
                {
                    var virtualKey = (VirtualKeyCode)code;
                    new InputSimulator().Keyboard.KeyDown(virtualKey);
                }
            if (!ScreenShareService.Streams.ContainsKey(_authClient)) return;
            if (RunningAsService)
            {
                AgentClient.ScrollMouse(positive);
            }
            else
            {
                new InputSimulator().Mouse.VerticalScroll(direction);
            }
            if (!ScreenShareService.Streams.ContainsKey(_authClient)) return;

                if (RunningAsService)
                {

                    AgentClient.MoveMouse(x, y);
                }
                else
                {
                    var bounds = Display.GetWindowRectangle();
                    x = checked((int)Math.Round(x * (65535 / (double)bounds.Width)));
                    y = checked((int)Math.Round(y * (65535 / (double)bounds.Height)));
                    new InputSimulator().Mouse.MoveMouseTo(x, y);
                }
                Console.WriteLine("Error moving mouse");
            if (ScreenShareService.Streams.ContainsKey(_authClient))
            {
                if (RunningAsService)
                {
                    AgentClient.HandleRightClick();
                }
                else
                {
                    new InputSimulator().Mouse.RightButtonClick();
                }
            }
            if (ScreenShareService.Streams.ContainsKey(_authClient))
            {
                if (RunningAsService)
                {
                    AgentClient.HandleLeftMouseUp();
                }
                else
                {
                    new InputSimulator().Mouse.LeftButtonUp();
                }
            }
            if (ScreenShareService.Streams.ContainsKey(_authClient))
            {
                if (RunningAsService)
                {
                    AgentClient.HandleLeftMouseDown();
                }
                else

                {
                    new InputSimulator().Mouse.LeftButtonDown();
                }
            }
using AgentInterface.Settings;
using AgentInterface.Settings;
﻿#region

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Security;
using System.ServiceModel;
using System.Threading;
using System.Threading.Tasks;
using AgentInterface;
using AgentInterface.Api.Models;
using UlteriusServer.Utilities;

#endregion

namespace UlteriusServer.Api.Network
{
    public class UlteriusAgentClient
    {
        private IInputContract InputChannel { get; set; }

        private IFrameContract FrameChannel { get; set; }

        public void Start(bool keepAlive = true)
        {
            var inputAddress = "net.tcp://localhost/ulterius/agent/input/";
            var frameAddress = "net.pipe://localhost/ulterius/agent/frames/";

            var inputBinding = new NetTcpBinding
            {
                Security = new NetTcpSecurity
                {
                    Transport = { ProtectionLevel = ProtectionLevel.None },
                    Mode = SecurityMode.None
                },
                MaxReceivedMessageSize = int.MaxValue
            };
            var ep = new EndpointAddress(inputAddress);
            
            InputChannel = ChannelFactory<IInputContract>.CreateChannel(inputBinding, ep);
         

            var frameBinding = new NetNamedPipeBinding
            {
                Security = new NetNamedPipeSecurity
                {
                    Transport = { ProtectionLevel = ProtectionLevel.None },
                    Mode = NetNamedPipeSecurityMode.None
                },
                MaxReceivedMessageSize = int.MaxValue
            };
            var epf = new EndpointAddress(frameAddress);
            FrameChannel = ChannelFactory<IFrameContract>.CreateChannel(frameBinding, epf);


            if (!keepAlive) return;
            var task = new Task(KeepAlive);
            task.Start();
        }

        private void KeepAlive()
        {
            while (true)
            {
                Tools.RestartDaemon();
                var alive = ChannelActive();
                if (!alive)
                {
                    var agentList = Process.GetProcessesByName("UlteriusAgent");
                    if (agentList.Length == 0)
                    {
                        Tools.RestartAgent();
                    }
                    Start(false);
                }
                Thread.Sleep(1000);
            }
        }

        public void ScrollMouse(bool positive)
        {
            try
            {
                InputChannel?.MouseScroll(positive);
            }
            catch (EndpointNotFoundException)
            {
                //
            }
            catch (CommunicationException)
            {
                //
            }
        }

        public bool ChannelActive()
        {
            try
            {
                return FrameChannel != null && FrameChannel.KeepAlive();
            }
            catch (EndpointNotFoundException)
            {
                return false;
            }
            catch (CommunicationException)
            {
                return false;
            }
        }

        public FrameInformation GetCleanFrame()
        {
            try
            {
                return FrameChannel.GetCleanFrame();
            }
            catch (EndpointNotFoundException)
            {
                return null;
            }
            catch (TimeoutException)
            {
                return null;
            }
            catch (CommunicationException)
            {
                return null;
            }
        }

        public FrameInformation GetFullFrame()
        {
            try
            {
                return FrameChannel.GetFullFrame();
            }
            catch (EndpointNotFoundException)
            {
                return null;
            }
            catch (CommunicationException)
            {
                return null;
            }
        }

        public void HandleRightMouseDown()
        {
            try
            {
                InputChannel.HandleRightMouseDown();
            }
            catch (EndpointNotFoundException)
            {
            }
            catch (CommunicationException)
            {
            }
        }

        public void HandleRightMouseUp()
        {
            try
            {
                InputChannel.HandleRightMouseUp();
            }
            catch (EndpointNotFoundException)
            {
            }
            catch (CommunicationException)
            {
            }
        }

        public void MoveMouse(int x, int y)
        {
            try
            {
                InputChannel.MoveMouse(x, y);
            }
            catch (EndpointNotFoundException)
            {
            }
            catch (CommunicationException ex)
            {
                Console.WriteLine(ex.Message);
                Console.Write(ex.StackTrace);
            }
        }

        public void HandleLeftMouseDown()
        {
            try
            {
                InputChannel.HandleLeftMouseDown();
            }
            catch (EndpointNotFoundException)
            {
            }
            catch (CommunicationException)
            {
            }
        }

        public void HandleLeftMouseUp()
        {
            try
            {
                InputChannel.HandleLeftMouseUp();
            }
            catch (EndpointNotFoundException)
            {
            }
            catch (CommunicationException)
            {
            }
        }

        public void HandleKeyDown(List<int> keyCodes)
        {
            try
            {
                InputChannel.HandleKeyDown(keyCodes);
            }
            catch (EndpointNotFoundException)
            {
            }
            catch (CommunicationException)
            {
            }
        }

        public void HandleKeyUp(List<int> keyCodes)
        {
            try
            {
                InputChannel.HandleKeyUp(keyCodes);
            }
            catch (EndpointNotFoundException)
            {
            }
            catch (CommunicationException)
            {
            }
        }

        public void HandleRightClick()
        {
            try
            {
                InputChannel.HandleRightClick();
            }
            catch (EndpointNotFoundException)
            {
            }
            catch (CommunicationException)
            {
            }
        }

        public float GetGpuTemp(string gpuName)
        {
            try
            {
                var temp = InputChannel.GetGpuTemp(gpuName);
                return temp;
            }
            catch (EndpointNotFoundException)
            {
                return -1;
            }
            catch (CommunicationException)
            {
                return -1;
            }
        }

        public List<DisplayInformation> GetDisplayInformation()
        {
            try
            {
                return InputChannel.GetDisplayInformation();
            }
            catch (EndpointNotFoundException)
            {
                return null;
            }
            catch (CommunicationException)
            {
                return null;
            }
        }

        public List<float> GetCpuTemps()
        {
            try
            {
                return InputChannel.GetCpuTemps();
            }
            catch (EndpointNotFoundException)
            {
                return null;
            }
            catch (CommunicationException)
            {
                return null;
            }
        }


    }
}
using AgentInterface.Api.Models;
using AgentInterface.Api.System;
using static AgentInterface.Api.Win32.Display;
            var displayList = DisplayInformation();
            if (!UlteriusApiServer.RunningAsService) return displayList;
            var displayInfo = UlteriusApiServer.AgentClient.GetDisplayInformation();
            return displayInfo ?? displayList;
            return UlteriusApiServer.RunningAsService
                ? UlteriusApiServer.AgentClient.GetCpuTemps()
                : SystemData.GetCpuTemps();
            return _motherBoard;
                totalBytesReceived += networkInterface.GetIPv4Statistics().BytesReceived;
                totalBytesSent += networkInterface.GetIPv4Statistics().BytesSent;
                totalNetworkInterfaces = NetworkInterface.GetAllNetworkInterfaces().Length,
using AgentInterface.Settings;
using AgentInterface.Api.Win32;
            var file = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
                 "Ulterius Updater.exe /silentall -nofreqcheck");
            ProcessStarter.PROCESS_INFORMATION procInfo;
            ProcessStarter.StartProcessAndBypassUAC(file,  out procInfo);
﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.ExceptionServices;
using OpenHardwareMonitor.Hardware;

namespace AgentInterface.Api.System
{
   public  class SystemData
    {

        [HandleProcessCorruptedStateExceptions]
        public static float GetGpuTemp(string gpuName)
        {
            try
            {
                var myComputer = new Computer();
                myComputer.Open();
                //possible fix for gpu temps on laptops
                myComputer.GPUEnabled = true;
                float temp = -1;
                foreach (var hardwareItem in myComputer.Hardware)
                {
                    hardwareItem.Update();
                    switch (hardwareItem.HardwareType)
                    {
                        case HardwareType.GpuNvidia:
                            foreach (
                                var sensor in
                                    hardwareItem.Sensors.Where(
                                        sensor =>
                                            sensor.SensorType == SensorType.Temperature &&
                                            hardwareItem.Name.Contains(gpuName)))
                            {
                                if (sensor.Value != null)
                                {
                                    temp = (float)sensor.Value;
                                }
                            }
                            break;
                        case HardwareType.GpuAti:
                            foreach (
                                var sensor in
                                    hardwareItem.Sensors.Where(
                                        sensor =>
                                            sensor.SensorType == SensorType.Temperature &&
                                            hardwareItem.Name.Contains(gpuName)))
                            {
                                if (sensor.Value != null)
                                {
                                    temp = (float)sensor.Value;
                                }
                            }
                            break;
                    }
                }
                myComputer.Close();
                return temp;
            }
            catch (AccessViolationException)
            {
                return -1;
            }
        }

        public static List<float> GetCpuTemps()
        {
            var myComputer = new Computer();
            myComputer.Open();
            myComputer.CPUEnabled = true;
            var tempTemps = new List<float>();
            var procCount = Environment.ProcessorCount;
            for (var i = 0; i < procCount; i++)
            {
                tempTemps.Add(-1);
            }
            try
            {
                var temps = (from hardwareItem in myComputer.Hardware
                             where hardwareItem.HardwareType == HardwareType.CPU
                             from sensor in hardwareItem.Sensors
                             where sensor.SensorType == SensorType.Temperature
                             let value = sensor.Value
                             where value != null
                             where value != null
                             select (float)value).ToList();
                if (temps.Count != 0) return temps;
                myComputer.Close();
                return tempTemps;
            }
            catch (Exception)
            {
                myComputer.Close();
                return tempTemps;
            }
        }

    }
}
﻿#region

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using AgentInterface.Settings;
using Newtonsoft.Json;
using UlteriusServer.Api.Network;
using UlteriusServer.Api.Network.Messages;
using UlteriusServer.Api.Services.LocalSystem;
using UlteriusServer.Api.Services.Network;
using UlteriusServer.Api.Services.Update;
using UlteriusServer.Forms.Utilities;
using UlteriusServer.Utilities.Security;
using UlteriusServer.WebSocketAPI;
using UlteriusServer.WebSocketAPI.Authentication;
using vtortola.WebSockets;
using ScreenShareService = UlteriusServer.Api.Services.LocalSystem.ScreenShareService;

#endregion

namespace UlteriusServer.Api
{
    internal class UlteriusApiServer
    {
        public static ConcurrentDictionary<Guid, AuthClient> AllClients { get; set; }
        public static bool RunningAsService { get; set; }
        public static ScreenShareService ScreenShareService { get; set; }
        public static FileSearchService FileSearchService { get; set; }
        public static CronJobService CronJobService { get; set; }

        public static UlteriusAgentClient AgentClient { get; set; }

        /// <summary>
        ///     Start the API Server
        /// </summary>
        public static void Start()
        {
            PacketLoader.LoadPackets();
            var config = Config.Load();
            var clientUpdateService = new UpdateService();
            clientUpdateService.Start();
            FileSearchService = new FileSearchService(Path.Combine(AppEnvironment.DataPath, "fileIndex.db"));
            FileSearchService.Start();
            CronJobService = new CronJobService(Path.Combine(AppEnvironment.DataPath, "jobs.json"), Path.Combine(AppEnvironment.DataPath, "scripts"));
            CronJobService.ConfigureJobs();
            var apiPort = config.TaskServer.TaskServerPort;
            AllClients = new ConcurrentDictionary<Guid, AuthClient>();
            ScreenShareService = new ScreenShareService();
            var address = NetworkService.GetAddress();
            var webCamPort = config.Webcams.WebcamPort;
            var screenSharePort = config.ScreenShareService.ScreenSharePort;
            var endPoints = new List<IPEndPoint>
            {
                new IPEndPoint(address, apiPort),
                new IPEndPoint(address, webCamPort),
                new IPEndPoint(address, screenSharePort)
            };
            var server = new WebSocketEventListener(endPoints, new WebSocketListenerOptions
            {
                PingTimeout = TimeSpan.FromSeconds(2),
                NegotiationTimeout = TimeSpan.FromSeconds(2),
                WebSocketSendTimeout = TimeSpan.FromSeconds(2),
                WebSocketReceiveTimeout = TimeSpan.FromSeconds(2),
                ParallelNegotiations = Environment.ProcessorCount*2,
                NegotiationQueueCapacity = 256,
                TcpBacklog = 1000,
                OnHttpNegotiation = (request, response) =>
                {
                    if (request.Cookies["ConnectionId"] == null)
                        response.Cookies.Add(new Cookie("ConnectionId", Guid.NewGuid().ToString()));
                }
            });
            server.OnConnect += HandleConnect;
            server.OnDisconnect += HandleDisconnect;
            server.OnPlainTextMessage += HandlePlainTextMessage;
            server.OnEncryptedMessage += HandleEncryptedMessage;
            server.OnError += HandleError;
            server.Start();
            Log("Api Server started at " + address);
            if (RunningAsService)
            {
                AgentClient = new UlteriusAgentClient();
                AgentClient.Start();
            }
        }

        


        /// <summary>
        ///     Handles encrypted binary messages
        /// </summary>
        /// <param name="clientSocket"></param>
        /// <param name="message"></param>
        private static void HandleEncryptedMessage(WebSocket clientSocket, byte[] message)
        {
            var connectionId = CookieManager.GetConnectionId(clientSocket);
            AuthClient authClient;
            if (AllClients.TryGetValue(connectionId, out authClient))
            {
                var packetManager = new PacketManager(authClient, clientSocket, message);
                var packet = packetManager.GetPacket();
                packet?.HandlePacket();
            }
        }

        private static void HandleError(WebSocket websocket, Exception error)
        {
            Console.WriteLine(error.StackTrace + " " + error.Message);
        }

        /// <summary>
        ///     Handles plaintext JSON packets.
        /// </summary>
        /// <param name="clientSocket"></param>
        /// <param name="message"></param>
        private static void HandlePlainTextMessage(WebSocket clientSocket, string message)
        {
            var connectionId = CookieManager.GetConnectionId(clientSocket);
            AuthClient authClient;
            if (AllClients.TryGetValue(connectionId, out authClient))
            {
                var packetManager = new PacketManager(authClient, clientSocket, message);
                var packet = packetManager.GetPacket();
                packet?.HandlePacket();
            }
        }


        /// <summary>
        ///     Remove a client when it disconnects
        /// </summary>
        /// <param name="clientSocket"></param>
        private static void HandleDisconnect(WebSocket clientSocket)
        {
            var connectionId = CookieManager.GetConnectionId(clientSocket);
            AuthClient temp = null;
            if (AllClients.TryRemove(connectionId, out temp))
            {
                Console.WriteLine("Disconnection from " + clientSocket.RemoteEndpoint);
                var userCount = AllClients.Count;
                var extra = userCount < 1 ? "s" : string.Empty;
                UlteriusTray.ShowMessage($"There are now {userCount} user{extra} connected.", "A user disconnected!");
            }
        }

        /// <summary>
        ///     When a client connects, assign them a unique RSA keypair for handshake.
        /// </summary>
        /// <param name="clientSocket"></param>
        private static async void HandleConnect(WebSocket clientSocket)
        {
            var connectionId = CookieManager.GetConnectionId(clientSocket);
            AuthClient authClient;
            AllClients.TryGetValue(connectionId, out authClient);
            if (authClient != null)
            {
                if (RunningAsService)
                {
                    MessageQueueManager agentManager;
                    if (!authClient.MessageQueueManagers.TryGetValue(22005, out agentManager))
                    {
                        if (authClient.MessageQueueManagers.TryAdd(22005,
                            new MessageQueueManager()))
                        {
                            Console.WriteLine("Service Manager Started");
                        }
                    }
                }
                MessageQueueManager manager;
                //check if a manager for that port exist, if not, create one
                if (!authClient.MessageQueueManagers.TryGetValue(clientSocket.LocalEndpoint.Port, out manager))
                {
                    if (authClient.MessageQueueManagers.TryAdd(clientSocket.LocalEndpoint.Port,
                        new MessageQueueManager()))
                    {
                        Console.WriteLine("Manager started for " + clientSocket.LocalEndpoint.Port);
                    }
                }
                return;
            }
            Console.WriteLine("Connection from " + clientSocket.RemoteEndpoint);
            var rsa = new Rsa();
            rsa.GenerateKeyPairs();
            var client = new AuthClient
            {
                PublicKey = rsa.PublicKey,
                PrivateKey = rsa.PrivateKey,
                MessageQueueManagers = new ConcurrentDictionary<int, MessageQueueManager>()
            };
            client.MessageQueueManagers.TryAdd(clientSocket.LocalEndpoint.Port, new MessageQueueManager());
            AllClients.AddOrUpdate(connectionId, client, (key, value) => value);
            await SendWelcomeMessage(client, clientSocket);
        }

        /// <summary>
        ///     Sends a new user their unique RSA keypair
        /// </summary>
        /// <param name="client"></param>
        /// <param name="clientSocket"></param>
        private static async Task SendWelcomeMessage(AuthClient client, WebSocket clientSocket)
        {
            var welcomeMessage = JsonConvert.SerializeObject(new
            {
                endpoint = "connectedToUlterius",
                results = new
                {
                    message = "Ulterius server online!",
                    publicKey = Rsa.SecureStringToString(client.PublicKey)
                }
            });
            if (clientSocket != null)
            {
                try
                {
                    await clientSocket.WriteStringAsync(welcomeMessage, CancellationToken.None);
                    var userCount = AllClients.Count;
                    var extra = userCount > 1 ? "s" : string.Empty;
                    UlteriusTray.ShowMessage($"There are now {userCount} user{extra} connected.", "A new user connected!");
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Failed to write welcome message " + ex.Message );
                }
            }
        }

        private static void Log(string message)
        {
            Console.WriteLine(message);
        }
    }
namespace AgentInterface.Api.Win32
        static extern int GetCurrentThreadId();
namespace AgentInterface.Api.ScreenShare.DesktopDuplication
﻿#region

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using SharpDX;
using SharpDX.Direct3D;
using SharpDX.Direct3D11;
using SharpDX.DXGI;
using SharpDX.Mathematics.Interop;
using Device = SharpDX.Direct3D11.Device;
using MapFlags = SharpDX.Direct3D11.MapFlags;
using Point = System.Drawing.Point;
using Rectangle = SharpDX.Rectangle;
using Resource = SharpDX.DXGI.Resource;
using ResultCode = SharpDX.DXGI.ResultCode;

#endregion

namespace AgentInterface.Api.ScreenShare.DesktopDuplication
{
    /// <summary>
    ///     Provides access to frame-by-frame updates of a particular desktop (i.e. one monitor), with image and cursor
    ///     information.
    /// </summary>
    public class DesktopDuplicator
    {
        private readonly OutputDuplication _mDeskDupl;
        private readonly Device _mDevice;
        private readonly Texture2DDescription _mTextureDesc;
        private readonly int _mWhichOutputDevice;
        private Texture2D _desktopImageTexture;

        private Bitmap _finalImage1, _finalImage2;
        private OutputDuplicateFrameInformation _frameInfo;
        private bool _isFinalImage1;
        private OutputDescription _mOutputDesc;

      
        /// <summary>
        ///     Duplicates the output of the specified monitor on the specified graphics adapter.
        /// </summary>
        /// <param name="whichGraphicsCardAdapter">The adapter which contains the desired outputs.</param>
        /// <param name="whichOutputDevice">
        ///     The output device to duplicate (i.e. monitor). Begins with zero, which seems to
        ///     correspond to the primary monitor.
        /// </param>
        public DesktopDuplicator()
        {


            Adapter1 adapter;
            try
            {
                adapter = GetBestAdapter(out int bestAdapaterIndex);
                if (adapter == null) throw new SharpDXException();
                Console.WriteLine($"Using the {adapter.Description.Description} for screen share.");
            }
            catch (SharpDXException)
            {
                ScreenData.CanUseGpuAcceleration = false;
                throw new DesktopDuplicationException("Could not find the specified graphics card adapter.");
            }
            DeviceCreationFlags flags = DeviceCreationFlags.BgraSupport;
            _mDevice = new Device(adapter, flags, FeatureLevel.Level_11_0);
            Output output;
            try
            {
                output = adapter.GetOutput(0);
            }
            catch (SharpDXException)
            {
                ScreenData.CanUseGpuAcceleration = false;
                throw new DesktopDuplicationException("Could not find the specified output device.");
            }
            var output1 = output.QueryInterface<Output1>();
            _mOutputDesc = output.Description;
            _mTextureDesc = new Texture2DDescription
            {
                CpuAccessFlags = CpuAccessFlags.Read,
                BindFlags = BindFlags.None,
                Format = Format.B8G8R8A8_UNorm,
                Width = ((Rectangle) _mOutputDesc.DesktopBounds).Width,
                Height = ((Rectangle) _mOutputDesc.DesktopBounds).Height,
                OptionFlags = ResourceOptionFlags.None,
                MipLevels = 1,
                ArraySize = 1,
                SampleDescription = {Count = 1, Quality = 0},
                Usage = ResourceUsage.Staging
            };

            try
            {
                _mDeskDupl = output1.DuplicateOutput(_mDevice);
            }
            catch (SharpDXException ex)
            {
                if (ex.ResultCode.Code == ResultCode.NotCurrentlyAvailable.Result.Code)
                    throw new DesktopDuplicationException(
                        "There is already the maximum number of applications using the Desktop Duplication API running, please close one of the applications and try again.");
            }
        }

        private Bitmap FinalImage
        {
            get { return _isFinalImage1 ? _finalImage1 : _finalImage2; }
            set
            {
                if (_isFinalImage1)
                {
                    _finalImage2 = value;
                    _finalImage1?.Dispose();
                }
                else
                {
                    _finalImage1 = value;
                    _finalImage2?.Dispose();
                }
                _isFinalImage1 = !_isFinalImage1;
            }
        }

        /// <summary>
        ///     Finds the most capable graphics card.
        /// </summary>
        /// <returns></returns>
        private static Adapter1 GetBestAdapter(out int bestAdapterIndex)
        {
            using (var dxgiFactory = new Factory1())
            {
                Adapter1 bestAdapter = null;
                bestAdapterIndex = -1;
                var adapterIndex = -1;
                long bestVideoMemory = 0;
                long bestSystemMemory = 0;

                foreach (var dxgiAdapter in dxgiFactory.Adapters1)
                {
                    adapterIndex++;

                    // not skip the render only WARP device
                    if (dxgiAdapter.Description.VendorId != 0x1414 || dxgiAdapter.Description.DeviceId != 0x8c)
                        if (dxgiAdapter.Outputs == null || dxgiAdapter.Outputs.Length == 0)
                            continue;

                    var level = Device.GetSupportedFeatureLevel(dxgiAdapter);

                    if (level < FeatureLevel.Level_11_0)
                        continue;
                    long videoMemory = (uint) dxgiAdapter.Description.DedicatedVideoMemory;
                    long systemMemory = (uint) dxgiAdapter.Description.DedicatedSystemMemory;

                    if (bestAdapter != null && videoMemory <= bestVideoMemory &&
                        (videoMemory != bestVideoMemory || systemMemory <= bestSystemMemory)) continue;
                    bestAdapter = dxgiAdapter;
                    bestAdapterIndex = adapterIndex;
                    bestVideoMemory = videoMemory;
                    bestSystemMemory = systemMemory;
                }

                return bestAdapter;
            }
        }

        /// <summary>
        ///     Retrieves the latest desktop image and associated metadata.
        /// </summary>
        public DesktopFrame GetLatestFrame()
        {
            var frame = new DesktopFrame();
            // Try to get the latest frame; this may timeout
            var retrievalTimedOut = RetrieveFrame();
            if (retrievalTimedOut)
                return null;
            try
            {
                RetrieveFrameMetadata(frame);
                //we don't need cursor info
                //RetrieveCursorMetadata(frame);
                //we dont need a full frame
                //ProcessFrame(frame);
            }
            catch
            {
                ReleaseFrame();
            }
            try
            {
                ReleaseFrame();
            }
            catch
            {
                //    throw new DesktopDuplicationException("Couldn't release frame.");  
            }
            return frame;
        }

        private bool RetrieveFrame()
        {
            if (_desktopImageTexture == null)
                _desktopImageTexture = new Texture2D(_mDevice, _mTextureDesc);
            Resource desktopResource = null;
            _frameInfo = new OutputDuplicateFrameInformation();
            try
            {
                _mDeskDupl.AcquireNextFrame(500, out _frameInfo, out desktopResource);
            }
            catch (SharpDXException ex)
            {
                if (ex.ResultCode.Code == ResultCode.WaitTimeout.Result.Code)
                    return true;
                if (ex.ResultCode.Failure)
                {
                    //return true;
                    desktopResource?.Dispose();
                    throw new DesktopDuplicationException("Failed to acquire next frame.");
                }
            }
            using (var tempTexture = desktopResource?.QueryInterface<Texture2D>())
            {
                _mDevice.ImmediateContext.CopyResource(tempTexture, _desktopImageTexture);
            }
            desktopResource?.Dispose();
            return false;
        }

        private void RetrieveFrameMetadata(DesktopFrame frame)
        {
            if (_frameInfo.TotalMetadataBufferSize > 0)
            {
                // Get moved regions
                var movedRegionsLength = 0;
                var movedRectangles = new OutputDuplicateMoveRectangle[_frameInfo.TotalMetadataBufferSize];
                _mDeskDupl.GetFrameMoveRects(movedRectangles.Length, movedRectangles, out movedRegionsLength);
                frame.MovedRegions =
                    new MovedRegion[movedRegionsLength / Marshal.SizeOf(typeof(OutputDuplicateMoveRectangle))];
                for (var i = 0; i < frame.MovedRegions.Length; i++)
                {
                    var destRect = (Rectangle) movedRectangles[i].DestinationRect;
                    frame.MovedRegions[i] = new MovedRegion
                    {
                        Source = new Point(movedRectangles[i].SourcePoint.X, movedRectangles[i].SourcePoint.Y),
                        Destination =
                            new global::System.Drawing.Rectangle(destRect.X, destRect.Y, destRect.Width, destRect.Height)
                    };
                }

                // Get dirty regions
                var dirtyRegionsLength = 0;
                var dirtyRectangles = new RawRectangle[_frameInfo.TotalMetadataBufferSize];
                _mDeskDupl.GetFrameDirtyRects(dirtyRectangles.Length, dirtyRectangles, out dirtyRegionsLength);
                frame.UpdatedRegions =
                    new global::System.Drawing.Rectangle[dirtyRegionsLength / Marshal.SizeOf(typeof(Rectangle))];
                frame.FinishedRegions = new FinishedRegions[frame.UpdatedRegions.Length];
                for (var i = 0; i < frame.UpdatedRegions.Length; i++)
                {
                    var dirtyRect = (Rectangle) dirtyRectangles[i];
                    var rect = new global::System.Drawing.Rectangle(dirtyRect.X, dirtyRect.Y, dirtyRect.Width,
                        dirtyRect.Height);


                    frame.FinishedRegions[i] = new FinishedRegions
                    {
                        Destination = rect,
                        Frame = ExtractRect(rect.X, rect.Y, rect.Width, rect.Height)
                    };
                }
            }
            else
            {
                frame.MovedRegions = new MovedRegion[0];
                frame.UpdatedRegions = new global::System.Drawing.Rectangle[0];
            }
        }


        private Bitmap ExtractRect(int originX, int originY, int width, int height)
        {
            // Get the desktop capture screenTexture
            var mapSource = _mDevice.ImmediateContext.MapSubresource(_desktopImageTexture, 0, MapMode.Read,
                MapFlags.None);

            // Create Drawing.Bitmap

            var bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); //不能是ARGB
            var boundsRect = new global::System.Drawing.Rectangle(0, 0, width, height);

            // Copy pixels from screen capture Texture to GDI bitmap
            var mapDest = bitmap.LockBits(boundsRect, ImageLockMode.WriteOnly, bitmap.PixelFormat);
            var sourcePtr = mapSource.DataPointer;
            var destPtr = mapDest.Scan0;

            sourcePtr = IntPtr.Add(sourcePtr, originY * mapSource.RowPitch + originX * 4);
            for (var y = 0; y < height; y++)
            {
                // Copy a single line 

                Utilities.CopyMemory(destPtr, sourcePtr, width * 4);

                // Advance pointers
                if (y != height - 1)
                    sourcePtr = IntPtr.Add(sourcePtr, mapSource.RowPitch);
                destPtr = IntPtr.Add(destPtr, mapDest.Stride);
            }

            // Release source and dest locks
            bitmap.UnlockBits(mapDest);
            _mDevice.ImmediateContext.UnmapSubresource(_desktopImageTexture, 0);
            return bitmap;
        }

        private void ProcessFrame(DesktopFrame frame)
        {
            // Get the desktop capture texture
            var mapSource = _mDevice.ImmediateContext.MapSubresource(_desktopImageTexture, 0, MapMode.Read,
                MapFlags.None);
            var bounds = (Rectangle) _mOutputDesc.DesktopBounds;
            FinalImage = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format32bppArgb);
            var boundsRect = new global::System.Drawing.Rectangle(0, 0, bounds.Width, bounds.Height);
            // Copy pixels from screen capture Texture to GDI bitmap
            var mapDest = FinalImage.LockBits(boundsRect, ImageLockMode.WriteOnly, FinalImage.PixelFormat);
            var sourcePtr = mapSource.DataPointer;
            var destPtr = mapDest.Scan0;
            for (var y = 0; y < bounds.Height; y++)
            {
                // Copy a single line 
                Utilities.CopyMemory(destPtr, sourcePtr, bounds.Width * 4);

                // Advance pointers
                sourcePtr = IntPtr.Add(sourcePtr, mapSource.RowPitch);
                destPtr = IntPtr.Add(destPtr, mapDest.Stride);
            }

            // Release source and dest locks
            FinalImage.UnlockBits(mapDest);
            _mDevice.ImmediateContext.UnmapSubresource(_desktopImageTexture, 0);
            frame.DesktopImage = (Bitmap) FinalImage.Clone();
        }

        private void ReleaseFrame()
        {
            try
            {
                _mDeskDupl.ReleaseFrame();
            }
            catch (SharpDXException ex)
            {
                if (ex.ResultCode.Failure)
                    throw new DesktopDuplicationException("Failed to release frame.");
            }
        }
    }
using System.Runtime.Serialization;
namespace AgentInterface.Api.ScreenShare.DesktopDuplication
    [DataContract]
        [DataMember]
        [DataMember]
        [DataMember]
        [DataMember]
        [DataMember]
        [DataMember]
        [DataMember]
        [DataMember]
        [DataMember]
﻿using System;
using System.Drawing;
using System.Runtime.Serialization;
namespace AgentInterface.Api.ScreenShare.DesktopDuplication
    [DataContract]
        [DataMember]
        [DataMember]
namespace AgentInterface.Api.ScreenShare.DesktopDuplication
namespace AgentInterface.Api.Models
using System.Runtime.Serialization;
using AgentInterface.Api.ScreenShare.DesktopDuplication;
namespace AgentInterface.Api.Models
    [DataContract]
        [DataMember]
        [DataMember]
        [DataMember]
        [DataMember]
﻿namespace AgentInterface.Api.Models
using AgentInterface.Api.Models;
using AgentInterface.Api.ScreenShare.DesktopDuplication;
using AgentInterface.Api.Win32;
using AgentInterface.Settings;
namespace AgentInterface.Api.ScreenShare
                _desktopDuplicator = new DesktopDuplicator();
                _desktopDuplicator = new DesktopDuplicator();
namespace AgentInterface.Api.Win32
namespace AgentInterface.Api.Win32
namespace AgentInterface.Api.Win32
namespace AgentInterface.Api.Win32
﻿<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    
  </configSections>
  <system.net>
    <settings>
      <httpWebRequest useUnsafeHeaderParsing="true" />
    </settings>
  </system.net>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
  </startup>
  <runtime>
    <loadFromRemoteSources enabled="true" />
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="AForge.Video" publicKeyToken="cbfb6e07d173c401" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-2.2.5.0" newVersion="2.2.5.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Magnum" publicKeyToken="b800c4cfcdeea87b" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-2.1.3.0" newVersion="2.1.3.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="vtortola.WebSockets" publicKeyToken="7f78616efb4a208d" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-2.2.1.0" newVersion="2.2.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="vtortola.WebSockets.Rfc6455" publicKeyToken="7f78616efb4a208d" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-2.2.1.0" newVersion="2.2.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="vtortola.WebSockets.Deflate" publicKeyToken="7f78616efb4a208d" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-2.2.1.0" newVersion="2.2.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="AForge" publicKeyToken="c1db6ff4eaa06aeb" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-2.2.5.0" newVersion="2.2.5.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Threading.Tasks.Dataflow" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.6.1.0" newVersion="4.6.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="SharpDX" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.2.0" newVersion="3.0.2.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="SharpDX.DXGI" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.2.0" newVersion="3.0.2.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="v13.0" />
      </parameters>
    </defaultConnectionFactory>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
      <provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
    </providers>
  </entityFramework>
  
﻿<?xml version="1.0" encoding="utf-8"?>
<Weavers>
  <Costura>
    <ExcludeAssemblies>
      WindowsInput
      AgentInterface
      Newtonsoft.Json
    </ExcludeAssemblies>
  </Costura>
</Weavers>
using AgentInterface.Settings;
using AgentInterface.Settings;
using Topshelf;
using UlteriusServer.Forms.Utilities;
using UlteriusServer.Utilities.Usage;

                if (
                    Process.GetProcessesByName(Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location))
                        .Count() > 1) return;

                ProfileOptimization.SetProfileRoot(AppEnvironment.DataPath);
                ProfileOptimization.StartProfile("Startup.Profile");

                if (args.Length > 0)
                    HostFactory.Run(x => //1
                    {
                        x.Service<UlteriusAgent>(s => //2
                        {
                            s.ConstructUsing(name => new UlteriusAgent()); //3
                            s.WhenStarted(tc => tc.Start()); //4
                            s.WhenStopped(tc => tc.Stop());
                            s.WhenSessionChanged((se, e, id) => { se.HandleEvent(e, id); }); //5
                        });
                        x.RunAsLocalSystem(); //6
                        x.EnableSessionChanged();
                        x.EnableServiceRecovery(r => { r.RestartService(1); });
                        x.SetDescription("The server that powers Ulterius"); //7
                        x.SetDisplayName("Ulterius Server"); //8
                        x.SetServiceName("UlteriusServer"); //9
                    });
                else
                    var ulterius = new Ulterius();
                    ulterius.Start();
                    var hardware = new HardwareSurvey();
                    hardware.Setup();
                    if (Tools.RunningPlatform() == Tools.Platform.Windows)
                        UlteriusTray.ShowTray();
                    else
                        Console.ReadKey(true);
                Console.Read();
[assembly: AssemblyVersion("1.9.2.0")]
[assembly: AssemblyFileVersion("1.9.2.0")]
using AgentInterface.Settings;
                    Console.WriteLine(queueRequest);
                    _ws.Close();

            _wsServer = new WebSocketListener(endpoint, new WebSocketListenerOptions
                OnHttpNegotiation = HttpNegotiation
            });
            var rfc6455 = new WebSocketFactoryRfc6455(_wsServer);
            _wsServer.Standards.RegisterStandard(rfc6455);
            _wsServer.Start();
            _log.Info("Echo Server started");
        private void HttpNegotiation(WebSocketHttpRequest request, WebSocketHttpResponse response)
                    _log.Error("Error Accepting clients", aex.GetBaseException());
            _log.Info("Server Stop accepting clients");
using AgentInterface.Settings;
            if (Process.GetProcessesByName(
                Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location))
                .Length > 1)
            {
                Process.GetCurrentProcess().Kill();
            }
            if (!Directory.Exists(AppEnvironment.DataPath))
            {
                Directory.CreateDirectory(AppEnvironment.DataPath);
            }

            if (!Debugger.IsAttached)
            {

                ExceptionHandler.AddGlobalHandlers();
                Console.WriteLine("Exception Handlers Attached");
            }


           
            var settings = Config.Load();

        
           
          
          
        
            Console.Write($"Service: {UlteriusApiServer.RunningAsService}");
﻿#region

using System;
using System.Diagnostics;
using Topshelf;
using UlteriusServer.Utilities;
using UlteriusServer.Utilities.Usage;

#endregion

namespace UlteriusServer
{
    public class UlteriusAgent
    {


        private Ulterius _ulterius;

        public void Start()
        {
            _ulterius = new Ulterius();
            _ulterius.Start(true);
            HandleMonitor();
            var hardware = new HardwareSurvey();
            hardware.Setup(true);
            Console.ReadLine();
        }

       
        public void HandleMonitor()
        {
            Tools.RestartAgent();
        }


        public void Stop()
        {
            var agentList = Process.GetProcessesByName("UlteriusAgent");
            foreach (var agent in agentList)
            {
                try
                {
                    agent.Kill();
                }
                catch (Exception)
                {
                    // ignored
                }
            }
            var managerList = Process.GetProcessesByName("DaemonManager");
            foreach (var manager in managerList)
            {
                try
                {
                    manager.Kill();
                }
                catch (Exception)
                {
                    // ignored
                }
            }

            var serverInstanceList = Process.GetProcessesByName("Ulterius Server");
            foreach (var server in serverInstanceList)
            {
                try
                {
                    server.Kill();
                }
                catch (Exception)
                {
                    // ignored
                }
            }
        }

        public void HandleEvent(HostControl hostControl, SessionChangedArguments arg3)
        {
            HandleMonitor();
        }
    }
}
﻿<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="..\packages\Microsoft.Net.Compilers.2.0.0-rc3\build\Microsoft.Net.Compilers.props" Condition="Exists('..\packages\Microsoft.Net.Compilers.2.0.0-rc3\build\Microsoft.Net.Compilers.props')" />
  <Import Project="..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.3\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props" Condition="Exists('..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.3\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" />
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{E9A365D5-AEBE-4AF3-86C5-D17BC65ADE46}</ProjectGuid>
    <OutputType>Exe</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>UlteriusServer</RootNamespace>
    <AssemblyName>Ulterius Server</AssemblyName>
    <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
    <NuGetPackageImportStamp>
    </NuGetPackageImportStamp>
    <TargetFrameworkProfile />
    <IsWebBootstrapper>false</IsWebBootstrapper>
    <PublishUrl>publish\</PublishUrl>
    <Install>true</Install>
    <InstallFrom>Disk</InstallFrom>
    <UpdateEnabled>false</UpdateEnabled>
    <UpdateMode>Foreground</UpdateMode>
    <UpdateInterval>7</UpdateInterval>
    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
    <UpdatePeriodically>false</UpdatePeriodically>
    <UpdateRequired>false</UpdateRequired>
    <MapFileExtensions>true</MapFileExtensions>
    <ApplicationRevision>0</ApplicationRevision>
    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
    <UseApplicationTrust>false</UseApplicationTrust>
    <BootstrapperEnabled>true</BootstrapperEnabled>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <Prefer32Bit>false</Prefer32Bit>
    <LangVersion>6</LangVersion>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <LangVersion>6</LangVersion>
    <Prefer32Bit>false</Prefer32Bit>
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
  </PropertyGroup>
  <PropertyGroup />
  <PropertyGroup />
  <PropertyGroup />
  <PropertyGroup>
    <ApplicationManifest>app.manifest</ApplicationManifest>
  </PropertyGroup>
  <PropertyGroup>
    <ApplicationIcon>256.ico</ApplicationIcon>
  </PropertyGroup>
  <PropertyGroup>
    <StartupObject />
  </PropertyGroup>
  <PropertyGroup>
    <SignAssembly>false</SignAssembly>
  </PropertyGroup>
  <PropertyGroup>
    <AssemblyOriginatorKeyFile>
    </AssemblyOriginatorKeyFile>
  </PropertyGroup>
  <PropertyGroup>
    <SignManifests>false</SignManifests>
  </PropertyGroup>
  <ItemGroup>
    <Compile Include="Api\Network\Messages\MessageResolver.cs" />
    <Compile Include="Api\Network\Messages\PacketLoader.cs" />
    <Compile Include="Api\Network\Messages\RectangleConverter.cs" />
    <Compile Include="Api\Network\Models\FanInformation.cs" />
    <Compile Include="Api\Network\Models\LoginInformation.cs" />
    <Compile Include="Api\Network\PacketHandlers\DisplayPacketHandler.cs" />
    <Compile Include="Api\Network\UlteriusAgentClient.cs" />
    <Compile Include="Api\Services\LocalSystem\Daemons\JobModel.cs" />
    <Compile Include="Api\Network\PacketHandlers\CronJobPacketHandler.cs" />
    <Compile Include="Api\Services\LocalSystem\Daemons\CronDaemon.cs" />
    <Compile Include="Api\Services\LocalSystem\Daemons\CronJob.cs" />
    <Compile Include="Api\Services\LocalSystem\Daemons\CronSchedule.cs" />
    <Compile Include="Api\Services\LocalSystem\CronJobService.cs" />
    <Compile Include="Api\Services\Update\UpdateService.cs" />
    <Compile Include="Api\Network\Messages\Message.cs" />
    <Compile Include="Api\Network\Messages\MessageQueueManager.cs" />
    <Compile Include="Api\Services\LocalSystem\FileSearchService.cs" />
    <Compile Include="Forms\Utilities\AboutBox.cs">
      <SubType>Form</SubType>
    </Compile>
    <Compile Include="Forms\Utilities\AboutBox.Designer.cs">
      <DependentUpon>AboutBox.cs</DependentUpon>
    </Compile>
    <Compile Include="TerminalServer\Infrastructure\ILogger.cs" />
    <Compile Include="TerminalServer\Infrastructure\Log4NetLogger.cs" />
    <Compile Include="Ulterius.cs" />
    <Compile Include="UlteriusAgent.cs" />
    <Compile Include="Utilities\Drive\PartitionModel.cs" />
    <Compile Include="Utilities\Drive\SmartData.cs" />
    <Compile Include="Utilities\Drive\SmartEnums.cs" />
    <Compile Include="Utilities\Drive\SmartModel.cs" />
    <Compile Include="Utilities\Extensions\NetworkBrowser.cs" />
    <Compile Include="Utilities\Extensions\TaskExtensions.cs" />
    <Compile Include="Utilities\Files\Database\DatabaseController.cs" />
    <Compile Include="Utilities\Files\Database\DatabaseManager.cs" />
    <Compile Include="Utilities\Security\Streams\OfbStream.cs" />
    <Compile Include="Utilities\Security\Streams\ZeroStream.cs" />
    <Compile Include="Utilities\Security\AuthUtils.cs" />
    <Compile Include="Utilities\Usage\HardwareSurvey.cs" />
    <Compile Include="WebCams\WebCamManager.cs" />
    <Compile Include="WebSocketAPI\Authentication\AuthClient.cs" />
    <Compile Include="Forms\Utilities\UlteriusTray.cs" />
    <Compile Include="Api\Network\Messages\Packet.cs" />
    <Compile Include="Api\Network\Messages\MessageBuilder.cs" />
    <Compile Include="Api\Network\PacketHandler.cs" />
    <Compile Include="Api\Network\PacketHandlers\ErrorPacketHandler.cs" />
    <Compile Include="Api\Network\PacketManager.cs" />
    <Compile Include="Api\Network\PacketHandlers\WebCamPacketHandler.cs" />
    <Compile Include="Api\Network\PacketHandlers\FilePacketHandler.cs" />
    <Compile Include="Api\Network\PacketHandlers\GpuPacketHandler.cs" />
    <Compile Include="Api\Network\PacketHandlers\ScreenSharePacketHandler.cs" />
    <Compile Include="Api\Network\PacketHandlers\AccountPacketHandler.cs" />
    <Compile Include="Api\Network\PacketHandlers\SettingsPacketHandler.cs" />
    <Compile Include="Api\Network\PacketHandlers\NetworkPacketHandler.cs" />
    <Compile Include="Api\Network\PacketHandlers\CpuPacketHandler.cs" />
    <Compile Include="Api\Network\PacketHandlers\OperatingSystemPacketHandler.cs" />
    <Compile Include="Api\Network\PacketHandlers\ProcessPacketHandler.cs" />
    <Compile Include="Api\Network\PacketHandlers\ServerPacketHandler.cs" />
    <Compile Include="Api\Network\PacketHandlers\SystemPacketHandler.cs" />
    <Compile Include="Api\Network\Models\GpuInformation.cs" />
    <Compile Include="Api\Services\LocalSystem\ScreenShareService.cs" />
    <Compile Include="TerminalServer\Cli\CommandSession.cs" />
    <Compile Include="TerminalServer\Cli\PowerShellSession.cs" />
    <Compile Include="TerminalServer\Cli\_ICliSession.cs" />
    <Compile Include="TerminalServer\Cli\_ICliSessionFactory.cs" />
    <Compile Include="TerminalServer\Infrastructure\SystemInfo.cs" />
    <Compile Include="TerminalServer\Infrastructure\_ISystemInfo.cs" />
    <Compile Include="TerminalServer\Messaging\Connection\ConnectionConnectRequest.cs" />
    <Compile Include="TerminalServer\Messaging\Connection\IConnectionEvent.cs" />
    <Compile Include="TerminalServer\Messaging\Connection\IConnectionRequest.cs" />
    <Compile Include="TerminalServer\Messaging\IMessageBus.cs" />
    <Compile Include="TerminalServer\Messaging\Serialization\DefaultEventSerializator.cs" />
    <Compile Include="TerminalServer\Messaging\Serialization\IEventSerializator.cs" />
    <Compile Include="TerminalServer\Messaging\TerminalControl\Events\ClosedTerminalEvent.cs" />
    <Compile Include="TerminalServer\Messaging\TerminalControl\Events\CreatedTerminalEvent.cs" />
    <Compile Include="TerminalServer\Messaging\TerminalControl\Events\SessionStateEvent.cs" />
    <Compile Include="TerminalServer\Messaging\TerminalControl\Events\TerminalOutputEvent.cs" />
    <Compile Include="TerminalServer\Messaging\TerminalControl\Events\_ITerminalEvent.cs" />
    <Compile Include="TerminalServer\Messaging\TerminalControl\Handlers\AesHandshakeRequestHandler.cs" />
    <Compile Include="TerminalServer\Messaging\TerminalControl\Handlers\CloseTerminalRequestHandler.cs" />
    <Compile Include="TerminalServer\Messaging\TerminalControl\Handlers\CreateTerminalRequestHandler.cs" />
    <Compile Include="TerminalServer\Messaging\TerminalControl\Handlers\InputTerminalRequestHandler.cs" />
    <Compile Include="TerminalServer\Messaging\TerminalControl\Handlers\_IRequestHandler.cs" />
    <Compile Include="TerminalServer\Messaging\TerminalControl\Requests\AesHandshakeRequest.cs" />
    <Compile Include="TerminalServer\Messaging\TerminalControl\Requests\CloseTerminalRequest.cs" />
    <Compile Include="TerminalServer\Messaging\TerminalControl\Requests\CreateTerminalRequest.cs" />
    <Compile Include="TerminalServer\Messaging\TerminalControl\Requests\TerminalInputRequest.cs" />
    <Compile Include="TerminalServer\Messaging\TerminalControl\Requests\_TerminalControlRequest.cs" />
    <Compile Include="TerminalServer\Messaging\WebSocketHandler.cs" />
    <Compile Include="TerminalServer\Messaging\WebSocketQueueServer.cs" />
    <Compile Include="TerminalServer\Session\ConnectionManager.cs" />
    <Compile Include="TerminalServer\Session\UserConnection.cs" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Api\UlteriusApiServer.cs" />
    <Compile Include="TerminalServer\TerminalManagerServer.cs" />
    <Compile Include="Utilities\DynamicMap.cs" />
    <Compile Include="Utilities\Extensions\StringExtensions.cs" />
    <Compile Include="Utilities\Files\FileManager.cs" />
    <Compile Include="Utilities\IconTools.cs" />
    <Compile Include="Utilities\Security\UlteriusAes.cs" />
    <Compile Include="Utilities\Security\Rsa.cs" />
    <Compile Include="Utilities\Files\FileTree.cs" />
    <Compile Include="Utilities\Trace.cs" />
    <Compile Include="WebServer\MultipartParser.cs" />
    <Compile Include="WebSocketAPI\Authentication\CookieManager.cs" />
    <Compile Include="WebSocketAPI\WebSocketEventListener.cs" />
    <Compile Include="Api\Network\Models\DriveInformation.cs" />
    <Compile Include="Api\Network\Models\SystemInformation.cs" />
    <Compile Include="Api\Network\Models\NetworkInformation.cs" />
    <Compile Include="Api\Network\Models\CpuInformation.cs" />
    <Compile Include="Api\Network\Models\OperatingSystemInformation.cs" />
    <Compile Include="Program.cs" />
    <Compile Include="Properties\Resources.Designer.cs">
      <AutoGen>True</AutoGen>
      <DesignTime>True</DesignTime>
      <DependentUpon>Resources.resx</DependentUpon>
    </Compile>
    <Compile Include="Api\Network\Models\ProcessInformation.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
    <Compile Include="Utilities\ExceptionHandler.cs" />
    <Compile Include="Api\Services\Network\NetworkService.cs" />
    <Compile Include="Api\Services\LocalSystem\SystemService.cs" />
    <Compile Include="Utilities\Tools.cs" />
    <Compile Include="WebServer\HttpServer.cs" />
  </ItemGroup>
  <ItemGroup>
    <None Include="App.config" />
    <None Include="app.manifest" />
    <None Include="App1.config" />
    <None Include="packages.config" />
  </ItemGroup>
  <ItemGroup>
    <EmbeddedResource Include="Forms\Utilities\AboutBox.resx">
      <DependentUpon>AboutBox.cs</DependentUpon>
    </EmbeddedResource>
    <EmbeddedResource Include="Properties\Resources.resx">
      <Generator>ResXFileCodeGenerator</Generator>
      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
      <SubType>Designer</SubType>
    </EmbeddedResource>
  </ItemGroup>
  <ItemGroup>
    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
      <Visible>False</Visible>
      <ProductName>.NET Framework 3.5 SP1</ProductName>
      <Install>false</Install>
    </BootstrapperPackage>
  </ItemGroup>
  <ItemGroup>
    <Content Include="256.ico" />
    <EmbeddedResource Include="Packets.json" />
    <None Include="Resources\ApplicationIcon.ico" />
    <None Include="FodyWeavers.xml">
      <SubType>Designer</SubType>
    </None>
    <Content Include="twitter-profile.ico" />
  </ItemGroup>
  <ItemGroup>
    <WCFMetadata Include="Service References\" />
  </ItemGroup>
  <ItemGroup>
    <Folder Include="bin\Debug\" />
    <Folder Include="Utilities\Files\Models\" />
  </ItemGroup>
  <ItemGroup>
    <Reference Include="AForge, Version=2.2.5.0, Culture=neutral, PublicKeyToken=c1db6ff4eaa06aeb, processorArchitecture=MSIL">
      <HintPath>..\packages\AForge.2.2.5\lib\AForge.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="AForge.Imaging, Version=2.2.5.0, Culture=neutral, PublicKeyToken=ba8ddea9676ca48b, processorArchitecture=MSIL">
      <HintPath>..\packages\AForge.Imaging.2.2.5\lib\AForge.Imaging.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="AForge.Math, Version=2.2.5.0, Culture=neutral, PublicKeyToken=abba2e25397ee8c9, processorArchitecture=MSIL">
      <HintPath>..\packages\AForge.Math.2.2.5\lib\AForge.Math.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="AForge.Video, Version=2.2.5.0, Culture=neutral, PublicKeyToken=cbfb6e07d173c401, processorArchitecture=MSIL">
      <HintPath>..\packages\AForge.Video.2.2.5\lib\AForge.Video.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="AForge.Video.DirectShow, Version=2.2.5.0, Culture=neutral, PublicKeyToken=61ea4348d43881b7, processorArchitecture=MSIL">
      <HintPath>..\packages\AForge.Video.DirectShow.2.2.5\lib\AForge.Video.DirectShow.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="AForge.Vision, Version=2.2.5.0, Culture=neutral, PublicKeyToken=b612fa915eefaa06, processorArchitecture=MSIL">
      <HintPath>..\packages\AForge.Vision.2.2.5\lib\AForge.Vision.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="BouncyCastle.Crypto, Version=1.8.1.0, Culture=neutral, PublicKeyToken=0e99375e54769942">
      <HintPath>..\packages\BouncyCastle.1.8.1\lib\BouncyCastle.Crypto.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="DotNetZip, Version=1.10.1.0, Culture=neutral, PublicKeyToken=6583c7c814667745, processorArchitecture=MSIL">
      <HintPath>..\packages\DotNetZip.1.10.1\lib\net20\DotNetZip.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="log4net, Version=2.0.7.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
      <HintPath>..\packages\log4net.2.0.7\lib\net45-full\log4net.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="Magnum, Version=2.1.3.0, Culture=neutral, PublicKeyToken=b800c4cfcdeea87b, processorArchitecture=MSIL">
      <HintPath>..\packages\Magnum.2.1.3\lib\NET40\Magnum.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="MassTransit, Version=2.9.0.0, Culture=neutral, PublicKeyToken=b8e0e9f2f1e657fa, processorArchitecture=MSIL">
      <HintPath>..\packages\MassTransit.2.9.0\lib\net40\MassTransit.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
      <HintPath>..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.3\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="Mono.Cecil, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
      <HintPath>..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="Mono.Cecil.Mdb, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
      <HintPath>..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Mdb.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="Mono.Cecil.Pdb, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
      <HintPath>..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Pdb.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="Mono.Cecil.Rocks, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
      <HintPath>..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Rocks.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
      <HintPath>..\packages\Newtonsoft.Json.10.0.1-beta1\lib\net45\Newtonsoft.Json.dll</HintPath>
    </Reference>
    <Reference Include="Open.Nat, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f22a6a4582336c76, processorArchitecture=MSIL">
      <HintPath>..\packages\Open.NAT.2.1.0.0\lib\net45\Open.Nat.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="PresentationCore" />
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="System.DirectoryServices" />
    <Reference Include="System.DirectoryServices.AccountManagement" />
    <Reference Include="System.Drawing" />
    <Reference Include="System.IO.Compression" />
    <Reference Include="System.Management" />
    <Reference Include="System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\3.0\System.Management.Automation.dll</HintPath>
    </Reference>
    <Reference Include="System.Net" />
    <Reference Include="System.Net.Http" />
    <Reference Include="System.ServiceModel" />
    <Reference Include="System.ServiceProcess" />
    <Reference Include="System.Threading.Tasks.Dataflow, Version=4.6.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
      <HintPath>..\packages\System.Threading.Tasks.Dataflow.4.7.0\lib\portable-net45+win8+wpa81\System.Threading.Tasks.Dataflow.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="System.Web" />
    <Reference Include="System.Windows.Forms" />
    <Reference Include="System.Xaml" />
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System.Xml" />
    <Reference Include="Topshelf, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b800c4cfcdeea87b, processorArchitecture=MSIL">
      <HintPath>..\packages\Topshelf.4.0.3\lib\net452\Topshelf.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="vtortola.WebSockets, Version=2.2.2.0, Culture=neutral, PublicKeyToken=7f78616efb4a208d, processorArchitecture=MSIL">
      <HintPath>..\packages\vtortola.WebSocketListener.2.2.2.0\lib\net45\vtortola.WebSockets.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="vtortola.WebSockets.Deflate, Version=2.2.2.0, Culture=neutral, PublicKeyToken=7f78616efb4a208d, processorArchitecture=MSIL">
      <HintPath>..\packages\vtortola.WebSocketListener.2.2.2.0\lib\net45\vtortola.WebSockets.Deflate.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="vtortola.WebSockets.Rfc6455, Version=2.2.2.0, Culture=neutral, PublicKeyToken=7f78616efb4a208d, processorArchitecture=MSIL">
      <HintPath>..\packages\vtortola.WebSocketListener.2.2.2.0\lib\net45\vtortola.WebSockets.Rfc6455.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="WindowsBase" />
    <Reference Include="ZetaLongPaths, Version=1.0.0.14, Culture=neutral, PublicKeyToken=b764f59068f31f38, processorArchitecture=MSIL">
      <HintPath>..\packages\ZetaLongPaths.1.0.0.14\lib\net40-full\ZetaLongPaths.dll</HintPath>
      <Private>True</Private>
    </Reference>
  </ItemGroup>
  <ItemGroup>
    <COMReference Include="NetFwTypeLib">
      <Guid>{58FBCF7C-E7A9-467C-80B3-FC65E8FCCA08}</Guid>
      <VersionMajor>1</VersionMajor>
      <VersionMinor>0</VersionMinor>
      <Lcid>0</Lcid>
      <WrapperTool>tlbimp</WrapperTool>
      <Isolated>False</Isolated>
      <EmbedInteropTypes>True</EmbedInteropTypes>
    </COMReference>
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\..\inputsimulator2\WindowsInput\WindowsInput.csproj">
      <Project>{3549cd6f-80f8-450f-b99e-cf0a736b1f2a}</Project>
      <Name>WindowsInput</Name>
    </ProjectReference>
    <ProjectReference Include="..\AgentInterface\AgentInterface.csproj">
      <Project>{5c3b0b17-cbb7-4b4b-b527-1fab2bb96466}</Project>
      <Name>AgentInterface</Name>
    </ProjectReference>
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
    <PropertyGroup>
      <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
    </PropertyGroup>
    <Error Condition="!Exists('..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.3\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.3\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props'))" />
    <Error Condition="!Exists('..\packages\Microsoft.Net.Compilers.2.0.0-rc3\build\Microsoft.Net.Compilers.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Net.Compilers.2.0.0-rc3\build\Microsoft.Net.Compilers.props'))" />
    <Error Condition="!Exists('..\packages\Fody.1.29.3\build\dotnet\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Fody.1.29.3\build\dotnet\Fody.targets'))" />
    <Error Condition="!Exists('..\packages\Costura.Fody.2.0.0-beta0018\build\Costura.Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Costura.Fody.2.0.0-beta0018\build\Costura.Fody.targets'))" />
  </Target>
  <PropertyGroup>
    <PostBuildEvent>
    </PostBuildEvent>
  </PropertyGroup>
  <PropertyGroup>
    <PreBuildEvent>
    </PreBuildEvent>
  </PropertyGroup>
  <Target Name="AfterClean">
    <Delete Files="$(TargetDir)\*.dll" />
  </Target>
  <Target Name="AfterClean">
    <ItemGroup>
      <FilesToDelete Include="$(TargetDir)\*.dll" />
    </ItemGroup>
    <Delete Files="@(FilesToDelete)" />
  </Target>
  <UsingTask TaskName="CosturaCleanup" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" TaskFactory="CodeTaskFactory">
    <ParameterGroup>
      <Config Output="false" Required="true" ParameterType="Microsoft.Build.Framework.ITaskItem" />
      <Files Output="false" Required="true" ParameterType="Microsoft.Build.Framework.ITaskItem[]" />
    </ParameterGroup>
    <Task Evaluate="true">
      <Reference xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Include="System.Xml" />
      <Reference xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Include="System.Xml.Linq" />
      <Using xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Namespace="System" />
      <Using xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Namespace="System.IO" />
      <Using xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Namespace="System.Xml.Linq" />
      <Code xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Type="Fragment" Language="cs"><![CDATA[
var config = XElement.Load(Config.ItemSpec).Elements("Costura").FirstOrDefault();

if (config == null) return true;

var excludedAssemblies = new List<string>();
var attribute = config.Attribute("ExcludeAssemblies");
if (attribute != null)
    foreach (var item in attribute.Value.Split('|').Select(x => x.Trim()).Where(x => x != string.Empty))
        excludedAssemblies.Add(item);
var element = config.Element("ExcludeAssemblies");
if (element != null)
    foreach (var item in element.Value.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()).Where(x => x != string.Empty))
        excludedAssemblies.Add(item);

var filesToCleanup = Files.Select(f => f.ItemSpec).Where(f => !excludedAssemblies.Contains(Path.GetFileNameWithoutExtension(f), StringComparer.InvariantCultureIgnoreCase));

foreach (var item in filesToCleanup)
  File.Delete(item);
]]></Code>
    </Task>
  </UsingTask>
  <Target Name="CleanReferenceCopyLocalPaths" AfterTargets="AfterBuild;NonWinFodyTarget">
    <CosturaCleanup Config="FodyWeavers.xml" Files="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" />
  </Target>
  <Import Project="..\packages\Fody.1.29.3\build\dotnet\Fody.targets" Condition="Exists('..\packages\Fody.1.29.3\build\dotnet\Fody.targets')" />
  <Import Project="..\packages\Costura.Fody.2.0.0-beta0018\build\Costura.Fody.targets" Condition="Exists('..\packages\Costura.Fody.2.0.0-beta0018\build\Costura.Fody.targets')" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  
  -->
namespace AgentInterface.Settings
namespace AgentInterface.Settings
using AgentInterface.Settings;
﻿#region

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Web.UI;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

#endregion

namespace UlteriusServer.Utilities.Extensions
{
    /// <summary>
    ///     Enum FormatTokenFlags
    /// </summary>
    public enum FormatTokenFlags
    {
        /// <summary>
        ///     Uses the specifier token as the replacement token, matches '%' but not '%%'
        /// </summary>
        SpecifierToken,

        /// <summary>
        ///     Like String.Format
        /// </summary>
        IndexToken,

        /// <summary>
        ///     Extracts an Object's Members by name.
        /// </summary>
        MemberToken
    }

    /// <summary>
    ///     Class StringExtensions
    /// </summary>
    public static class StringExtensions
    {

        // Returns the human-readable file totalSize for an arbitrary, 64-bit file totalSize 
        // The default format is "0.### XB", e.g. "4.2 KB" or "1.434 GB"

        public static string UnicodeUtf8(this string strFrom)
        {
            var bytSrc = Encoding.Unicode.GetBytes(strFrom);
            var bytDestination = Encoding.Convert(Encoding.Unicode, Encoding.UTF8, bytSrc);
            var strTo = Encoding.UTF8.GetString(bytDestination);
            return strTo;
        }

        /// <summary>
        /// Implement's VB's Like operator logic.
        /// </summary>
        public static bool IsLike(this string s, string pattern)
        {
            // Characters matched so far
            int matched = 0;

            // Loop through pattern string
            for (int i = 0; i < pattern.Length;)
            {
                // Check for end of string
                if (matched > s.Length)
                    return false;

                // Get next pattern character
                char c = pattern[i++];
                if (c == '[') // Character list
                {
                    // Test for exclude character
                    bool exclude = (i < pattern.Length && pattern[i] == '!');
                    if (exclude)
                        i++;
                    // Build character list
                    int j = pattern.IndexOf(']', i);
                    if (j < 0)
                        j = s.Length;
                    HashSet<char> charList = CharListToSet(pattern.Substring(i, j - i));
                    i = j + 1;

                    if (charList.Contains(s[matched]) == exclude)
                        return false;
                    matched++;
                }
                else if (c == '?') // Any single character
                {
                    matched++;
                }
                else if (c == '#') // Any single digit
                {
                    if (!Char.IsDigit(s[matched]))
                        return false;
                    matched++;
                }
                else if (c == '*') // Zero or more characters
                {
                    if (i < pattern.Length)
                    {
                        // Matches all characters until
                        // next character in pattern
                        char next = pattern[i];
                        int j = s.IndexOf(next, matched);
                        if (j < 0)
                            return false;
                        matched = j;
                    }
                    else
                    {
                        // Matches all remaining characters
                        matched = s.Length;
                        break;
                    }
                }
                else // Exact character
                {
                    if (matched >= s.Length || c != s[matched])
                        return false;
                    matched++;
                }
            }
            // Return true if all characters matched
            return (matched == s.Length);
        }

        /// <summary>
        /// Converts a string of characters to a HashSet of characters. If the string
        /// contains character ranges, such as A-Z, all characters in the range are
        /// also added to the returned set of characters.
        /// </summary>
        /// <param name="charList">Character list string</param>
        private static HashSet<char> CharListToSet(string charList)
        {
            HashSet<char> set = new HashSet<char>();

            for (int i = 0; i < charList.Length; i++)
            {
                if ((i + 1) < charList.Length && charList[i + 1] == '-')
                {
                    // Character range
                    char startChar = charList[i++];
                    i++; // Hyphen
                    char endChar = (char)0;
                    if (i < charList.Length)
                        endChar = charList[i++];
                    for (int j = startChar; j <= endChar; j++)
                        set.Add((char)j);
                }
                else set.Add(charList[i]);
            }
            return set;
        }

        public static string GetBytesReadable(long i)
        {
            // Get absolute value
            var absoluteI = i < 0 ? -i : i;
            // Determine the suffix and readable value
            string suffix;
            double readable;
            if (absoluteI >= 0x1000000000000000) // Exabyte
            {
                suffix = "EB";
                readable = i >> 50;
            }
            else if (absoluteI >= 0x4000000000000) // Petabyte
            {
                suffix = "PB";
                readable = i >> 40;
            }
            else if (absoluteI >= 0x10000000000) // Terabyte
            {
                suffix = "TB";
                readable = i >> 30;
            }
            else if (absoluteI >= 0x40000000) // Gigabyte
            {
                suffix = "GB";
                readable = i >> 20;
            }
            else if (absoluteI >= 0x100000) // Megabyte
            {
                suffix = "MB";
                readable = i >> 10;
            }
            else if (absoluteI >= 0x400) // Kilobyte
            {
                suffix = "KB";
                readable = i;
            }
            else
            {
                return i.ToString("0 B"); // Byte
            }
            // Divide by 1024 to get fractional value
            readable = readable / 1024;
            // Return formatted number with suffix
            return readable.ToString("0.### ") + suffix;
        }

        /// <summary>
        /// Returns a Secure string from the source string
        /// </summary>
        /// <param name="Source"></param>
        /// <returns></returns>
        public static SecureString ToSecureString(this string Source)
        {
            if (string.IsNullOrWhiteSpace(Source))
                return null;
            var Result = new SecureString();
            foreach (var c in Source.ToCharArray())
                Result.AppendChar(c);
            return Result;
        }
        public static string ToUnsecureString(this SecureString secureString)
        {
            if (secureString == null) throw new ArgumentNullException("secureString");

            var unmanagedString = IntPtr.Zero;
            try
            {
                unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(secureString);
                return Marshal.PtrToStringUni(unmanagedString);
            }
            finally
            {
                Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString);
            }
        }


        /// <summary>
        ///     The Reformatting function called to format the string with a list of arguments.
        /// </summary>
        private static Func<Func<string, object>, string, IList<object>, string> _regexReformatter;

        /// <summary>
        ///     The Regex which matches the specifier token in strings.
        /// </summary>
        private static Regex _specifierTokenRegex;

        /// <summary>
        ///     The Regex which matches parameter indexes in strings, same as string.Format.
        /// </summary>
        private static Regex _argumentIndexRegex;

        /// <summary>
        ///     The Regex which matches object member names in strings.
        /// </summary>
        private static Regex _objectMemberRegex;

        /// <summary>
        ///     Splits a string into an array of strings, the string is split by commas.
        /// </summary>
        /// <param name="this">The string instance to split by commas.</param>
        /// <returns>The <paramref name="this" /> string that has been comma separated into substrings.</returns>
        public static string[] CommaSeparate(this string @this)
        {
            return @this.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
        }

        /// <summary>
        ///     Determines whether two String objects contain the same data, ignoring the case of the letters in the String; uses
        ///     Ordinal comparison.
        /// </summary>
        /// <param name="this">The current string to be compared to.</param>
        /// <param name="other">The other string to compare against the current String for equality.</param>
        /// <returns><c>true</c> if the two strings are equal, <c>false</c> otherwise</returns>
        public static bool EqualsIgnoreCase(this string @this, string other)
        {
            return string.Equals(@this, other, StringComparison.OrdinalIgnoreCase);
        }

        public static bool IsBase64String(this string s)
        {
            s = s.Trim();
            return (s.Length%4 == 0) && Regex.IsMatch(s, @"^[a-zA-Z0-9\+/]*={0,3}$", RegexOptions.None);
        }

        public static bool IsValidJson(this string strInput)
        {
            strInput = strInput.Trim();
            if ((strInput.StartsWith("{") && strInput.EndsWith("}")) || //For object
                (strInput.StartsWith("[") && strInput.EndsWith("]"))) //For array
            {
                try
                {
                    JToken.Parse(strInput);
                    return true;
                }
                catch (JsonReaderException)
                {
                    //Exception in parsing json
                    return false;
                }
                catch (Exception) //some other exception
                {
                    return false;
                }
            }
            return false;
        }


        /// <summary>
        ///     Replaces one or more format items in a specified string with the string representation of a specified object.
        /// </summary>
        /// <returns>
        ///     A copy of <paramref name="format" /> in which any format items are replaced by the string representation of
        ///     <paramref name="values" />.
        /// </returns>
        /// <param name="format">A composite format string. </param>
        /// <param name="values">The arguments to use in formatting <paramref name="format" />.</param>
        public static string Form(this string format, params object[] values)
        {
            var specifierTokenMatches = _specifierTokenRegex.Matches(format);
            var indexTokenMatches = _argumentIndexRegex.Matches(format);
            var memberNameMatches = _objectMemberRegex.Matches(format);

            if (memberNameMatches.Count > 0 && values.Length == 1)
            {
                format = FormatString(format, FormatTokenFlags.MemberToken, values);
            }
            else
            {
                if (indexTokenMatches.Count > 0)
                {
                    format = FormatString(format, FormatTokenFlags.IndexToken, values);
                }

                if (specifierTokenMatches.Count > 0)
                {
                    format = FormatString(format, FormatTokenFlags.SpecifierToken, values);
                }
            }
            return format;
        }

        public static string CreateMD5(this string input)
        {
            // Use input string to calculate MD5 hash
            using (var md5 = MD5.Create())
            {
                var inputBytes = Encoding.ASCII.GetBytes(input);
                var hashBytes = md5.ComputeHash(inputBytes);

                // Convert the byte array to hexadecimal string
                var sb = new StringBuilder();
                foreach (var t in hashBytes)
                {
                    sb.Append(t.ToString("X2"));
                }
                return sb.ToString();
            }
        }

        /// <summary>
        ///     The Function which does all the heavy lifting.
        /// </summary>
        /// <param name="format">A composite format string</param>
        /// <param name="flags">The flags which specify how the <paramref name="format" /> string should be interpreted.</param>
        /// <param name="arguments">The arguments to format the <paramref name="format" /> parameter with.</param>
        /// <returns>System.String.</returns>
        public static string FormatString(string format, FormatTokenFlags flags, params object[] arguments)
        {
            switch (flags)
            {
                case FormatTokenFlags.IndexToken:
                    return string.Format(format, arguments);

                case FormatTokenFlags.SpecifierToken:
                    var stringBuilder = new StringBuilder();
                    for (int i = 0,
                        argIndex = 0;
                        i < format.Length;
                        i++)
                    {
                        stringBuilder.Append(format[i] == '%' && argIndex < arguments.Length
                            ? "{" + argIndex++ + "}"
                            : format.Substring(i, 1));
                    }
                    return string.Format(stringBuilder.ToString(), arguments);

                case FormatTokenFlags.MemberToken:
                    return
                        string.Format(
                            _regexReformatter(name => name == "0" ? arguments[0] : DataBinder.Eval(arguments[0], name),
                                format, arguments), arguments);

                default:
                    return format;
            }
        }

        public static void Initialize()
        {
            const RegexOptions regexOptions = RegexOptions.Compiled | RegexOptions.CultureInvariant;
            _objectMemberRegex = new Regex(@"(?<start>(\{))+(?<property>[\w\.]+)(?<end>(\}))+", regexOptions);
            _specifierTokenRegex = new Regex(@"(?<!\\)%", regexOptions);
            _argumentIndexRegex = new Regex(@"\{(\d)\}", regexOptions);
            _regexReformatter = (valueFetcher, format, parameters) =>
            {
                var argumentCollection = new List<object>();
                var rewrittenFormat = _objectMemberRegex.Replace(format, match =>
                {
                    Group startGroup = match.Groups["start"],
                        propertyGroup = match.Groups["property"],
                        endGroup = match.Groups["end"];

                    var result = valueFetcher(propertyGroup.Value);

                    argumentCollection.Add(result);
                    var index = argumentCollection.Count - 1;
                    var fmt = new string('{', startGroup.Captures.Count) + index +
                              new string('}', endGroup.Captures.Count);
                    return string.Format(fmt, argumentCollection.ToArray());
                });

                return rewrittenFormat;
            };
        }
    }
using AgentInterface.Api.Win32;

using AgentInterface.Api.ScreenShare;
using AgentInterface.Api.Win32;
using AgentInterface.Settings;
                ProcessStarter.PROCESS_INFORMATION managerInfo;
                ProcessStarter.StartProcessAndBypassUAC(managerPath, 
                out managerInfo);
                managerProcess = Process.GetProcessById((int)managerInfo.dwProcessId);

               
            ProcessStarter.PROCESS_INFORMATION agentInfo;
        
         
            var agentPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),"UlteriusAgent.exe");
            
            ProcessStarter.StartProcessAndBypassUAC(agentPath, 
                out agentInfo);
            agentProcess = Process.GetProcessById((int)agentInfo.dwProcessId);
            if (!RunningAsService())
            {
              ScreenData.SetupDuplication();  
            }
                    if (RunningAsService())
                    {
                        ProcessStarter.PROCESS_INFORMATION procInfo;
                        ProcessStarter.StartProcessAndBypassUAC("CMD.exe " + command,  out procInfo);
                    }
                    else
                    {
                        Process.Start("CMD.exe", command);
                    }
                        string.Format(
                            "firewall add allowedprogram program=\"{0}\" name=\"{1}\" profile=\"ALL\"",
                            exeFileName, displayName),
            proc.WaitForExit();
            return GetCurrent().Name.ToLower().Contains(@"nt authority\system");
using AgentInterface.Settings;
﻿#region

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Management;
using System.Net.Http;
using System.Reflection;
using System.Windows.Forms;
using Microsoft.Win32;
using Newtonsoft.Json;
using UlteriusServer.Api.Network.Models;
using UlteriusServer.Properties;
using SystemInformation = UlteriusServer.Api.Network.Models.SystemInformation;

#endregion

namespace UlteriusServer.Utilities.Usage
{
    public class HardwareSurvey
    {
        private static readonly string results = "surveryresults.json";

        private List<GpuInformation> GetGpuInformation()
        {
            var searcher =
                new ManagementObjectSearcher("SELECT * FROM Win32_VideoController");

            var gpus = (from ManagementBaseObject mo in searcher.Get()
                select new GpuInformation
                {
                    Name = mo["Name"]?.ToString(),
                    ScreenInfo = mo["VideoModeDescription"]?.ToString(),
                    DriverVersion = mo["DriverVersion"]?.ToString(),
                    RefreshRate = int.Parse(mo["CurrentRefreshRate"]?.ToString() ?? "0"),
                    AdapterRam = mo["AdapterRAM"]?.ToString(),
                    VideoArchitecture = int.Parse(mo["VideoArchitecture"]?.ToString() ?? "0"),
                    VideoMemoryType = int.Parse(mo["VideoMemoryType"]?.ToString() ?? "0"),
                    InstalledDisplayDrivers = mo["InstalledDisplayDrivers"]?.ToString()?.Split(','),
                    AdapterCompatibility = mo["AdapterCompatibility"]?.ToString(),
                    Status = mo["Status"]?.ToString(),
                    Availability = int.Parse(mo["Availability"]?.ToString() ?? "0")
                }).ToList();
            return gpus;
        }

        private void Prompt()
        {
            var dialogResult = MessageBox.Show(Resources.HardwareSurvey_Setup_,
                Resources.HardwareSurvey_Setup_Usage_statistics_reporting, MessageBoxButtons.YesNo);
            switch (dialogResult)
            {
                case DialogResult.Yes:
                    SendData();
                    break;
                case DialogResult.No:
                    File.WriteAllText(results, "false");
                    break;
            }
        }

        public void Setup(bool service = false)
        {
            if (File.Exists(results))
            {
                var days = (DateTime.Now - File.GetCreationTime(results)).TotalDays;
                if (days > 30)
                {
                    SendData();
                }
            }
            else
            {
                if (service)
                {
                    SendData();
                }
                else
                {
                    Prompt();
                }
            }
        }

        public string GetMachineGuid()
        {
            try
            {
                var location = @"SOFTWARE\Microsoft\Cryptography";
                var name = "MachineGuid";
                using (var localMachineX64View =
                    RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64))
                {
                    using (var rk = localMachineX64View.OpenSubKey(location))
                    {
                        if (rk == null)
                            throw new KeyNotFoundException(
                                $"Key Not Found: {location}");

                        var machineGuid = rk.GetValue(name);
                        if (machineGuid == null)
                            throw new IndexOutOfRangeException(
                                $"Index Not Found: {name}");
                        return machineGuid.ToString().Replace("-", "").ToUpper();
                    }
                }
            }
            catch (Exception)
            {
                return Guid.NewGuid().ToString("N").ToUpper();
            }
        }

        private async void SendData()
        {
            try
            {
                var data = new
                {
                    ServerInfo = OperatingSystemInformation.ToObject(),
                    SystemInfo = SystemInformation.ToObject(),
                    UlteriusVersion = Assembly.GetExecutingAssembly().GetName().Version,
                    GpuInfo = GetGpuInformation(),
                    NetworkInformation = NetworkInformation.ToObject(),
                    CpuInfo = CpuInformation.ToObject()
                };
                var json = JsonConvert.SerializeObject(data);
                var content = new FormUrlEncodedContent(new[]
                {
                    new KeyValuePair<string, string>("guid", GetMachineGuid()),
                    new KeyValuePair<string, string>("results", json)
                });
                using (var client = new HttpClient())
                {
                    client.Timeout = new TimeSpan(0, 0, 0, 5);
                    var result = await client.PostAsync("https://api.ulterius.io/hardware/", content);
                    if (result.IsSuccessStatusCode)
                    {
                        Console.WriteLine("Hardware Survery Completed");
                        File.WriteAllText(results, "true");
                    }
                }
            }
            catch (Exception)
            {
                //just fail
            }
        }
    }
}
using AgentInterface.Settings;
using AgentInterface.Settings;


        private readonly List<WebSocketListener> _listeners = new List<WebSocketListener>();
        public WebSocketEventListener(List<IPEndPoint> endpoints)
        public WebSocketEventListener(List<IPEndPoint> endpoints, WebSocketListenerOptions options)
            foreach (var endpoint in endpoints)
            {
                var listener = new WebSocketListener(endpoint, options);
                var rfc6455 = new WebSocketFactoryRfc6455(listener);
                listener.Standards.RegisterStandard(rfc6455);
                _listeners.Add(listener);
            }
            foreach (var listener in _listeners)
            {
                listener.Dispose();
            }
        public void Start()
            foreach (var listener in _listeners)
            {
                listener.Start();
            }
        public void Stop()
            foreach (var listener in _listeners)
            {
                listener.Stop();
            }
            foreach (var listener in _listeners)
            {
                Task.Run(() => HandleListners(listener));
            }
﻿<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="AForge" version="2.2.5" targetFramework="net461" />
  <package id="AForge.Imaging" version="2.2.5" targetFramework="net461" />
  <package id="AForge.Math" version="2.2.5" targetFramework="net461" />
  <package id="AForge.Video" version="2.2.5" targetFramework="net461" />
  <package id="AForge.Video.DirectShow" version="2.2.5" targetFramework="net461" />
  <package id="AForge.Vision" version="2.2.5" targetFramework="net461" />
  <package id="BouncyCastle" version="1.8.1" targetFramework="net461" />
  <package id="Costura.Fody" version="2.0.0-beta0018" targetFramework="net461" developmentDependency="true" />
  <package id="DotNetZip" version="1.10.1" targetFramework="net461" />
  <package id="Fody" version="1.29.3" targetFramework="net461" developmentDependency="true" />
  <package id="JonSkeet.MiscUtil" version="0.1" targetFramework="net45" />
  <package id="log4net" version="2.0.7" targetFramework="net461" />
  <package id="Magnum" version="2.1.3" targetFramework="net461" />
  <package id="MassTransit" version="2.9.0" targetFramework="net461" />
  <package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="1.0.3" targetFramework="net461" />
  <package id="Microsoft.Net.Compilers" version="2.0.0-rc3" targetFramework="net461" developmentDependency="true" />
  <package id="Microsoft.Tpl.Dataflow" version="4.5.24" targetFramework="net461" />
  <package id="Mono.Cecil" version="0.9.6.4" targetFramework="net461" />
  <package id="Newtonsoft.Json" version="10.0.1-beta1" targetFramework="net461" />
  <package id="Open.NAT" version="2.1.0.0" targetFramework="net461" />
  <package id="System.Threading.Tasks.Dataflow" version="4.7.0" targetFramework="net461" />
  <package id="Topshelf" version="4.0.3" targetFramework="net461" />
  <package id="vtortola.WebSocketListener" version="2.2.2.0" targetFramework="net461" />
  <package id="ZetaLongPaths" version="1.0.0.14" targetFramework="net461" />
﻿<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
    </startup>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Magnum" publicKeyToken="b800c4cfcdeea87b" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-2.1.3.0" newVersion="2.1.3.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="AsyncIO" publicKeyToken="44a94435bd6f33f8" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-0.1.25.0" newVersion="0.1.25.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>
﻿<?xml version="1.0" encoding="utf-8"?>
<Weavers>
  <Costura>
    <ExcludeAssemblies>
      WindowsInput
      AgentInterface
      Newtonsoft.Json
    </ExcludeAssemblies>
  </Costura>
</Weavers>
﻿#region

using System;
using System.Drawing;
using System.ServiceModel;
using AgentInterface;
using AgentInterface.Api.Models;
using AgentInterface.Api.ScreenShare;
using AgentInterface.Api.Win32;


#endregion

namespace UlteriusAgent.Networking
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    public class FrameAgent : IFrameContract
    {
        private string _lastDesktop;
        private Desktop _lastDesktopInput;


        public FrameInformation GetCleanFrame()
        {
            HandleDesktop();
            var setCurrent = Desktop.SetCurrent(_lastDesktopInput);
            return !setCurrent ? null : ScreenData.DesktopCapture();
        }

        public FrameInformation GetFullFrame()
        {
            HandleDesktop();
            var tempBounds = Display.GetWindowRectangle();
            var frameInfo = new FrameInformation
            {
                Bounds = tempBounds,
                ScreenImage = ScreenData.CaptureDesktop()
            };
            if (frameInfo.ScreenImage != null) return frameInfo;
            var bmp = new Bitmap(frameInfo.Bounds.Width, frameInfo.Bounds.Height);
            using (var gfx = Graphics.FromImage(bmp))
            using (var brush = new SolidBrush(Color.FromArgb(67, 75, 99)))
            {
                gfx.FillRectangle(brush, 0, 0, frameInfo.Bounds.Width, frameInfo.Bounds.Height);
            }
            frameInfo.ScreenImage = bmp;
            return frameInfo;
        }

        public bool KeepAlive()
        {
            return true;
        }

        private void HandleDesktop()
        {
            using (var inputDesktop = new Desktop())
            {
                inputDesktop.OpenInput();
                if (!inputDesktop.DesktopName.Equals(_lastDesktop))
                {
                    var switched = inputDesktop.Show();

                    if (switched)
                    {
                        var setCurrent = Desktop.SetCurrent(inputDesktop);
                        if (setCurrent)
                        {
                            Console.WriteLine($"Desktop switched from {_lastDesktop} to {inputDesktop.DesktopName}");
                            _lastDesktop = inputDesktop.DesktopName;
                            _lastDesktopInput = inputDesktop;
                        }
                        else
                        {
                            _lastDesktopInput.Close();
                        }
                    }
                }
                else
                {
                    inputDesktop.Close();
                }
            }
           
        }
    }
}
﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.ExceptionServices;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
using WindowsInput;
using WindowsInput.Native;
using AgentInterface;
using AgentInterface.Api.Models;
using AgentInterface.Api.System;
using AgentInterface.Api.Win32;

namespace UlteriusAgent.Networking
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    public class InputAgent : IInputContract
    {

        public void HandleRightMouseDown()
        {
            var inputDesktop = new Desktop();
            inputDesktop.OpenInput();
            var setCurrent = Desktop.SetCurrent(inputDesktop);
            if (setCurrent)
            {
                new InputSimulator().Mouse.RightButtonDown();
            }
        }

        public void HandleRightMouseUp()
        {
            var inputDesktop = new Desktop();
            inputDesktop.OpenInput();
            var setCurrent = Desktop.SetCurrent(inputDesktop);
            if (setCurrent)
            {
                new InputSimulator().Mouse.RightButtonUp();
            }

        }

        public void MoveMouse(int x, int y)
        {
            var inputDesktop = new Desktop();
            inputDesktop.OpenInput();
            var setCurrent = Desktop.SetCurrent(inputDesktop);
            if (setCurrent)
            {
                var bounds = Display.GetWindowRectangle();
                x = checked((int)Math.Round(x * (65535 / (double)bounds.Width)));
                y = checked((int)Math.Round(y * (65535 / (double)bounds.Height)));
                new InputSimulator().Mouse.MoveMouseTo(x, y);
            }
        }

        public void MouseScroll(bool positive)
        {
            var inputDesktop = new Desktop();
            inputDesktop.OpenInput();
            var setCurrent = Desktop.SetCurrent(inputDesktop);
            if (setCurrent)
            {
                var direction = positive ? 10 : -10;
                new InputSimulator().Mouse.VerticalScroll(direction);
            }

        }


        public void HandleLeftMouseDown()
        {
            var inputDesktop = new Desktop();
            inputDesktop.OpenInput();
            var setCurrent = Desktop.SetCurrent(inputDesktop);
            if (setCurrent)
            {
                new InputSimulator().Mouse.LeftButtonDown();
            }


        }

        public void HandleLeftMouseUp()
        {
            var inputDesktop = new Desktop();
            inputDesktop.OpenInput();
            var setCurrent = Desktop.SetCurrent(inputDesktop);
            if (setCurrent)
            {
                new InputSimulator().Mouse.LeftButtonUp();
            }


        }

        public void HandleKeyDown(List<int> keyCodes)
        {
            var inputDesktop = new Desktop();
            inputDesktop.OpenInput();
            var setCurrent = Desktop.SetCurrent(inputDesktop);
            if (setCurrent)
            {
                foreach (var code in keyCodes)
                {
                    var virtualKey = (VirtualKeyCode)code;
                    new InputSimulator().Keyboard.KeyDown(virtualKey);

                }
            }

        }

        public void HandleKeyUp(List<int> keyCodes)
        {
            var inputDesktop = new Desktop();
            inputDesktop.OpenInput();
            var setCurrent = Desktop.SetCurrent(inputDesktop);
            if (setCurrent)
            {
                foreach (var code in keyCodes)
                {
                    var virtualKey = (VirtualKeyCode)code;
                    new InputSimulator().Keyboard.KeyUp(virtualKey);
                }
            }

        }

        public void HandleRightClick()
        {
            var inputDesktop = new Desktop();
            inputDesktop.OpenInput();
            var setCurrent = Desktop.SetCurrent(inputDesktop);
            if (setCurrent)
            {
                new InputSimulator().Mouse.RightButtonClick();
            }
        }

        [HandleProcessCorruptedStateExceptions]
        public float GetGpuTemp(string gpuName)
        {
            return SystemData.GetGpuTemp(gpuName);
        }

        public List<DisplayInformation> GetDisplayInformation()
        {
            return Display.DisplayInformation();
        }


        public List<float> GetCpuTemps()
        {
            return SystemData.GetCpuTemps();
        }
    }
}
﻿#region

using System;
using System.Diagnostics;
using System.Linq;

#endregion

namespace UlteriusAgent.Networking
{
    public static class Tools
    {
        public static void KillAllButMe()
        {
            try
            {
                var current = Process.GetCurrentProcess();
                //kill any other agent that may be running
                var processes = Process.GetProcessesByName(current.ProcessName)
                    .Where(t => t.Id != current.Id)
                    .ToList();
                foreach (var process in processes)
                {
                    process.Kill();
                    process.WaitForExit();
                }
            }
            catch (Exception)
            {
                // ignored
            }
        }
    }
}
using System;
using System.Collections.ObjectModel;
using System.Net.Security;
using System.Runtime.InteropServices;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using AgentInterface;
using AgentInterface.Api.ScreenShare;
using UlteriusAgent.Networking;
  
        private const int SW_HIDE = 0;
        private const int SW_SHOW = 5;

        [DllImport("user32.dll")]
        private static extern bool SetProcessDPIAware();

        [DllImport("kernel32.dll")]
        private static extern IntPtr GetConsoleWindow();

        [DllImport("user32.dll")]
        private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);


            if (Environment.OSVersion.Version.Major >= 6)
                SetProcessDPIAware();
            }
            var handle = GetConsoleWindow();

            // Hide
            ShowWindow(handle, SW_HIDE);

            Tools.KillAllButMe();
            try
                ScreenData.SetupDuplication();
                var inputAddress = "net.tcp://localhost/ulterius/agent/input/";
                var frameAddress = "net.pipe://localhost/ulterius/agent/frames/";
               
                var inputService = new ServiceHost(typeof(InputAgent));
                var frameService = new ServiceHost(typeof(FrameAgent));
                var inputBinding = new NetTcpBinding
                {
                    Security = new NetTcpSecurity
                    {
                        Transport = {ProtectionLevel = ProtectionLevel.None},
                        Mode = SecurityMode.None
                    },
                    MaxReceivedMessageSize = int.MaxValue
                };
                var frameBinding = new NetNamedPipeBinding
                    Security = new NetNamedPipeSecurity
                    {
                        Transport = { ProtectionLevel = ProtectionLevel.None },
                        Mode = NetNamedPipeSecurityMode.None
                    },
                    MaxReceivedMessageSize = int.MaxValue
                };
                inputService.AddServiceEndpoint(typeof(IInputContract), inputBinding, inputAddress);
                frameService.AddServiceEndpoint(typeof(IFrameContract), frameBinding, frameAddress);
                inputService.Opened += delegate(object sender, EventArgs eventArgs)
                 {
                     Console.WriteLine("Input started");
                 };
                frameService.Opened += delegate (object sender, EventArgs eventArgs)
                    Console.WriteLine("Frame started");
                };
                inputService.Open();
                frameService.Open();
                Console.WriteLine("Test");
                Console.Read();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message + " \n " + ex.StackTrace);
            }
            Console.Read();
        }

        private static void host_faulted(object sender, EventArgs e)
        {
            
﻿<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{686AE4C4-791F-45EB-9414-029D6115905D}</ProjectGuid>
    <OutputType>Exe</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>UlteriusAgent</RootNamespace>
    <AssemblyName>UlteriusAgent</AssemblyName>
    <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
    <NuGetPackageImportStamp>
    </NuGetPackageImportStamp>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <Prefer32Bit>false</Prefer32Bit>
  </PropertyGroup>
  <PropertyGroup>
    <StartupObject />
  </PropertyGroup>
  <PropertyGroup>
    <ApplicationManifest>app.manifest</ApplicationManifest>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="System.Drawing" />
    <Reference Include="System.ServiceModel" />
    <Reference Include="System.Windows.Forms" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Networking\InputAgent.cs" />
    <Compile Include="Networking\FrameAgent.cs" />
    <Compile Include="Networking\Tools.cs" />
    <Compile Include="Program.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
  </ItemGroup>
  <ItemGroup>
    <None Include="App.config">
      <SubType>Designer</SubType>
    </None>
    <None Include="app.manifest" />
  </ItemGroup>
  <ItemGroup>
    <None Include="FodyWeavers.xml" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\..\inputsimulator2\WindowsInput\WindowsInput.csproj">
      <Project>{3549cd6f-80f8-450f-b99e-cf0a736b1f2a}</Project>
      <Name>WindowsInput</Name>
    </ProjectReference>
    <ProjectReference Include="..\AgentInterface\AgentInterface.csproj">
      <Project>{5c3b0b17-cbb7-4b4b-b527-1fab2bb96466}</Project>
      <Name>AgentInterface</Name>
    </ProjectReference>
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <UsingTask TaskName="CosturaCleanup" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" TaskFactory="CodeTaskFactory">
    <ParameterGroup>
      <Config Output="false" Required="true" ParameterType="Microsoft.Build.Framework.ITaskItem" />
      <Files Output="false" Required="true" ParameterType="Microsoft.Build.Framework.ITaskItem[]" />
    </ParameterGroup>
    <Task Evaluate="true">
      <Reference xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Include="System.Xml" />
      <Reference xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Include="System.Xml.Linq" />
      <Using xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Namespace="System" />
      <Using xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Namespace="System.IO" />
      <Using xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Namespace="System.Xml.Linq" />
      <Code xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Type="Fragment" Language="cs"><![CDATA[
var config = XElement.Load(Config.ItemSpec).Elements("Costura").FirstOrDefault();

if (config == null) return true;

var excludedAssemblies = new List<string>();
var attribute = config.Attribute("ExcludeAssemblies");
if (attribute != null)
    foreach (var item in attribute.Value.Split('|').Select(x => x.Trim()).Where(x => x != string.Empty))
        excludedAssemblies.Add(item);
var element = config.Element("ExcludeAssemblies");
if (element != null)
    foreach (var item in element.Value.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()).Where(x => x != string.Empty))
        excludedAssemblies.Add(item);

var filesToCleanup = Files.Select(f => f.ItemSpec).Where(f => !excludedAssemblies.Contains(Path.GetFileNameWithoutExtension(f), StringComparer.InvariantCultureIgnoreCase));

foreach (var item in filesToCleanup)
  File.Delete(item);
]]></Code>
    </Task>
  </UsingTask>
  <Target Name="CleanReferenceCopyLocalPaths" AfterTargets="AfterBuild;NonWinFodyTarget">
    <CosturaCleanup Config="FodyWeavers.xml" Files="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" />
  </Target>
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
﻿
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UlteriusServer", "RemoteTaskServer\UlteriusServer.csproj", "{E9A365D5-AEBE-4AF3-86C5-D17BC65ADE46}"
	ProjectSection(ProjectDependencies) = postProject
		{5C3B0B17-CBB7-4B4B-B527-1FAB2BB96466} = {5C3B0B17-CBB7-4B4B-B527-1FAB2BB96466}
		{3549CD6F-80F8-450F-B99E-CF0A736B1F2A} = {3549CD6F-80F8-450F-B99E-CF0A736B1F2A}
		{686AE4C4-791F-45EB-9414-029D6115905D} = {686AE4C4-791F-45EB-9414-029D6115905D}
	EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UlteriusAgent", "UlteriusAgent\UlteriusAgent.csproj", "{686AE4C4-791F-45EB-9414-029D6115905D}"
	ProjectSection(ProjectDependencies) = postProject
		{5C3B0B17-CBB7-4B4B-B527-1FAB2BB96466} = {5C3B0B17-CBB7-4B4B-B527-1FAB2BB96466}
		{3549CD6F-80F8-450F-B99E-CF0A736B1F2A} = {3549CD6F-80F8-450F-B99E-CF0A736B1F2A}
	EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AgentInterface", "AgentInterface\AgentInterface.csproj", "{5C3B0B17-CBB7-4B4B-B527-1FAB2BB96466}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsInput", "..\inputsimulator2\WindowsInput\WindowsInput.csproj", "{3549CD6F-80F8-450F-B99E-CF0A736B1F2A}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|Any CPU = Debug|Any CPU
		Release|Any CPU = Release|Any CPU
	EndGlobalSection
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
		{E9A365D5-AEBE-4AF3-86C5-D17BC65ADE46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{E9A365D5-AEBE-4AF3-86C5-D17BC65ADE46}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{E9A365D5-AEBE-4AF3-86C5-D17BC65ADE46}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{E9A365D5-AEBE-4AF3-86C5-D17BC65ADE46}.Release|Any CPU.Build.0 = Release|Any CPU
		{686AE4C4-791F-45EB-9414-029D6115905D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{686AE4C4-791F-45EB-9414-029D6115905D}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{686AE4C4-791F-45EB-9414-029D6115905D}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{686AE4C4-791F-45EB-9414-029D6115905D}.Release|Any CPU.Build.0 = Release|Any CPU
		{5C3B0B17-CBB7-4B4B-B527-1FAB2BB96466}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{5C3B0B17-CBB7-4B4B-B527-1FAB2BB96466}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{5C3B0B17-CBB7-4B4B-B527-1FAB2BB96466}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{5C3B0B17-CBB7-4B4B-B527-1FAB2BB96466}.Release|Any CPU.Build.0 = Release|Any CPU
		{3549CD6F-80F8-450F-B99E-CF0A736B1F2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{3549CD6F-80F8-450F-B99E-CF0A736B1F2A}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{3549CD6F-80F8-450F-B99E-CF0A736B1F2A}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{3549CD6F-80F8-450F-B99E-CF0A736B1F2A}.Release|Any CPU.Build.0 = Release|Any CPU
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
EndGlobal
Fixed code: .vs/
using vtortola.WebSockets.Http;
                var host = new Uri($"ws://{_client.HttpRequest.Headers[RequestHeader.Host]}", UriKind.Absolute);

                           

                                var targetPort = host.Port;
                    var targetPort = host.Port;
                var host = new Uri($"ws://{_client.HttpRequest.Headers[RequestHeader.Host]}", UriKind.Absolute);
                    var targetPort = host.Port;
using UlteriusServer.Api.Win32.ScreenShare.Models;
using UlteriusServer.Api.Win32;
           /* var device = _packet.Args[0].ToString();
            _builder.WriteMessage(formThread);*/
            /*var width = int.Parse(_packet.Args[0].ToString());
            _builder.WriteMessage(formThread);*/
            /*var width = int.Parse(_packet.Args[0].ToString());
            _builder.WriteMessage(formThread);*/
using UlteriusServer.Utilities;
            return SystemData.GetGpuTemp(gpuName);
using UlteriusServer.Api.Win32;
                var processStartInfo = new ProcessStartInfo(path);
                var process = new Process { StartInfo = processStartInfo };
                processStarted = process.Start();
                processId = process.Id;
using UlteriusServer.Api.Win32;
using UlteriusServer.Api.Win32.ScreenShare;
using UlteriusServer.Api.Win32.ScreenShare.DesktopDuplication;
                var stream = new Thread(GetScreenFrame) { IsBackground = true };
                if (RunningAsService && DesktopWatcher.CurrentDesktop != null)
                {
                    Desktop.SetCurrent(DesktopWatcher.CurrentDesktop);
                }
            if (RunningAsService && DesktopWatcher.CurrentDesktop != null)
            {
                Desktop.SetCurrent(DesktopWatcher.CurrentDesktop);
            }
                    HandleFullFrame();
            new InputSimulator().Mouse.RightButtonUp();
            new InputSimulator().Mouse.RightButtonDown();
            foreach (var code in codes)
                var virtualKey = (VirtualKeyCode)code;
                new InputSimulator().Keyboard.KeyUp(virtualKey);
            foreach (var code in codes)
                var virtualKey = (VirtualKeyCode)code;
                new InputSimulator().Keyboard.KeyDown(virtualKey);
            new InputSimulator().Mouse.VerticalScroll(direction);
                var bounds = Display.GetWindowRectangle();
                x = checked((int)Math.Round(x * (65535 / (double)bounds.Width)));
                y = checked((int)Math.Round(y * (65535 / (double)bounds.Height)));
                new InputSimulator().Mouse.MoveMouseTo(x, y);
                //Console.WriteLine("Error moving mouse");
            new InputSimulator().Mouse.RightButtonClick();
            new InputSimulator().Mouse.LeftButtonUp();
            new InputSimulator().Mouse.LeftButtonDown();
using UlteriusServer.Utilities;
using UlteriusServer.Utilities;
using System.Windows.Forms;
using UlteriusServer.Api.Win32;
using UlteriusServer.Api.Win32.ScreenShare.Models;
using SystemInformation = UlteriusServer.Api.Network.Models.SystemInformation;
            var displays = new List<DisplayInformation>();
            for (var i = 0; i < Screen.AllScreens.Length; i++)
            {
                var friendly = Display.GetDeviceFriendlyName(i);
                var display = new DisplayInformation {FriendlyName = friendly};
                var currentScreen = Screen.AllScreens[i];
                display.CurrentResolution = new ResolutionInformation
                {
                    BitsPerPixel = currentScreen.BitsPerPixel,
                    Frequency = 60,
                    Height = currentScreen.Bounds.Height,
                    Width = currentScreen.Bounds.Width,
                    Orientation = "Unknown",
                    X = currentScreen.Bounds.X,
                    Y = currentScreen.Bounds.Y
                };
                displays.Add(display);
            }
            return displays;
            return SystemData.GetCpuTemps();
            return string.IsNullOrEmpty(_motherBoard) ? "Board Unknown" : _motherBoard;
                totalBytesReceived += networkInterface?.GetIPv4Statistics()?.BytesReceived ?? 0;
                totalBytesSent += networkInterface?.GetIPv4Statistics()?.BytesSent ?? 0;
                totalNetworkInterfaces = NetworkInterface.GetAllNetworkInterfaces()?.Length ?? 0,
using UlteriusServer.Utilities;
using System.Diagnostics;
using UlteriusServer.Api.Win32;
            var file = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Ulterius Updater.exe /silentall -nofreqcheck");
            Process.Start(file);
﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.ExceptionServices;
using OpenHardwareMonitor.Hardware;

namespace UlteriusServer.Api
{
    public class SystemData
    {

        [HandleProcessCorruptedStateExceptions]
        public static float GetGpuTemp(string gpuName)
        {
            try
            {
                var myComputer = new Computer();
                myComputer.Open();
                //possible fix for gpu temps on laptops
                myComputer.GPUEnabled = true;
                float temp = -1;
                foreach (var hardwareItem in myComputer.Hardware)
                {
                    hardwareItem.Update();
                    switch (hardwareItem.HardwareType)
                    {
                        case HardwareType.GpuNvidia:
                            foreach (
                                var sensor in
                                hardwareItem.Sensors.Where(
                                    sensor =>
                                        sensor.SensorType == SensorType.Temperature &&
                                        hardwareItem.Name.Contains(gpuName)))
                            {
                                if (sensor.Value != null)
                                {
                                    temp = (float)sensor.Value;
                                }
                            }
                            break;
                        case HardwareType.GpuAti:
                            foreach (
                                var sensor in
                                hardwareItem.Sensors.Where(
                                    sensor =>
                                        sensor.SensorType == SensorType.Temperature &&
                                        hardwareItem.Name.Contains(gpuName)))
                            {
                                if (sensor.Value != null)
                                {
                                    temp = (float)sensor.Value;
                                }
                            }
                            break;
                    }
                }
                myComputer.Close();
                return temp;
            }
            catch (AccessViolationException)
            {
                return -1;
            }
        }

        public static List<float> GetCpuTemps()
        {
            var myComputer = new Computer();
            myComputer.Open();
            myComputer.CPUEnabled = true;
            var tempTemps = new List<float>();
            var procCount = Environment.ProcessorCount;
            for (var i = 0; i < procCount; i++)
            {
                tempTemps.Add(-1);
            }
            try
            {
                var temps = (from hardwareItem in myComputer.Hardware
                    where hardwareItem.HardwareType == HardwareType.CPU
                    from sensor in hardwareItem.Sensors
                    where sensor.SensorType == SensorType.Temperature
                    let value = sensor.Value
                    where value != null
                    where value != null
                    select (float)value).ToList();
                if (temps.Count != 0) return temps;
                myComputer.Close();
                return tempTemps;
            }
            catch (Exception)
            {
                myComputer.Close();
                return tempTemps;
            }
        }

    }
}
﻿#region

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
using UlteriusServer.Api.Network;
using UlteriusServer.Api.Network.Messages;
using UlteriusServer.Api.Services.LocalSystem;
using UlteriusServer.Api.Services.Network;
using UlteriusServer.Api.Services.Update;
using UlteriusServer.Forms.Utilities;
using UlteriusServer.Utilities;
using UlteriusServer.Utilities.Security;
using UlteriusServer.WebSocketAPI;
using UlteriusServer.WebSocketAPI.Authentication;
using vtortola.WebSockets;
using vtortola.WebSockets.Http;
using ScreenShareService = UlteriusServer.Api.Services.LocalSystem.ScreenShareService;

#endregion

namespace UlteriusServer.Api
{
    internal class UlteriusApiServer
    {
        public static ConcurrentDictionary<Guid, AuthClient> AllClients { get; set; }
        public static bool RunningAsService { get; set; }
        public static ScreenShareService ScreenShareService { get; set; }
        public static FileSearchService FileSearchService { get; set; }
        public static CronJobService CronJobService { get; set; }
        private static int _bufferSize = 1024 * 8;
        private static int _bufferPoolSize;

        /// <summary>
        ///     Start the API Server
        /// </summary>
        public static void Start()
        {
            _bufferPoolSize = 100 * _bufferSize;
            PacketLoader.LoadPackets();
            var config = Config.Load();
            var clientUpdateService = new UpdateService();
            clientUpdateService.Start();
            FileSearchService = new FileSearchService(Path.Combine(AppEnvironment.DataPath, "fileIndex.db"));
            FileSearchService.Start();
            CronJobService = new CronJobService(Path.Combine(AppEnvironment.DataPath, "jobs.json"), Path.Combine(AppEnvironment.DataPath, "scripts"));
            CronJobService.ConfigureJobs();
            var apiPort = config.TaskServer.TaskServerPort;
            AllClients = new ConcurrentDictionary<Guid, AuthClient>();
            ScreenShareService = new ScreenShareService();
            var address = NetworkService.GetAddress();
            var webCamPort = config.Webcams.WebcamPort;
            var screenSharePort = config.ScreenShareService.ScreenSharePort;
            var listenEndPoints = new Uri[] {
                new Uri($"ws://{address}:{apiPort}"),
                new Uri($"ws://{address}:{webCamPort}"),
                new Uri($"ws://{address}:{screenSharePort}")
            };
            var options = new WebSocketListenerOptions
            {
                PingMode = PingMode.LatencyControl,
                NegotiationTimeout = TimeSpan.FromSeconds(30),
                PingTimeout = TimeSpan.FromSeconds(5),
                ParallelNegotiations = 16,
                NegotiationQueueCapacity = 256,
                BufferManager = BufferManager.CreateBufferManager(_bufferPoolSize, _bufferSize),
                Logger = NullLogger.Instance,
                HttpAuthenticationHandler = async (request, response) =>
                {
                    await Task.Delay(TimeSpan.FromMilliseconds(1));
                    if (request.Cookies["ConnectionId"] == null)
                        response.Cookies.Add(new Cookie("ConnectionId", Guid.NewGuid().ToString()));
                    return true;
                }
            };
            options.Transports.ConfigureTcp(tcp =>
            {
                tcp.BacklogSize = 1000; // max pending connections waiting to be accepted
                tcp.ReceiveBufferSize = _bufferSize;
                tcp.SendBufferSize = _bufferSize;
                tcp.LingerState = new LingerOption(true, 0);
                tcp.NoDelay = true;
                tcp.IsAsync = true;
                
                tcp.ReceiveTimeout = TimeSpan.FromSeconds(1);
                tcp.SendTimeout = TimeSpan.FromSeconds(3);
            });

            var server = new WebSocketEventListener(listenEndPoints, options);
            server.OnConnect += HandleConnect;
            server.OnDisconnect += HandleDisconnect;
            server.OnPlainTextMessage += HandlePlainTextMessage;
            server.OnEncryptedMessage += HandleEncryptedMessage;
            server.OnError += HandleError;
            server.Start();
            Log("Api Server started at " + address);
        }

        


        /// <summary>
        ///     Handles encrypted binary messages
        /// </summary>
        /// <param name="clientSocket"></param>
        /// <param name="message"></param>
        private static void HandleEncryptedMessage(WebSocket clientSocket, byte[] message)
        {
            var connectionId = CookieManager.GetConnectionId(clientSocket);
            AuthClient authClient;
            if (AllClients.TryGetValue(connectionId, out authClient))
            {
                var packetManager = new PacketManager(authClient, clientSocket, message);
                var packet = packetManager.GetPacket();
                packet?.HandlePacket();
            }
        }

        private static void HandleError(WebSocket websocket, Exception error)
        {
            Console.WriteLine(error.StackTrace + " " + error.Message);
        }

        /// <summary>
        ///     Handles plaintext JSON packets.
        /// </summary>
        /// <param name="clientSocket"></param>
        /// <param name="message"></param>
        private static void HandlePlainTextMessage(WebSocket clientSocket, string message)
        {
            var connectionId = CookieManager.GetConnectionId(clientSocket);
            AuthClient authClient;
            if (AllClients.TryGetValue(connectionId, out authClient))
            {
                var packetManager = new PacketManager(authClient, clientSocket, message);
                var packet = packetManager.GetPacket();
                packet?.HandlePacket();
            }
        }


        /// <summary>
        ///     Remove a client when it disconnects
        /// </summary>
        /// <param name="clientSocket"></param>
        private static void HandleDisconnect(WebSocket clientSocket)
        {
            var connectionId = CookieManager.GetConnectionId(clientSocket);
            AuthClient temp = null;
            if (AllClients.TryRemove(connectionId, out temp))
            {
                Console.WriteLine("Disconnection from " + clientSocket.RemoteEndpoint);
                var userCount = AllClients.Count;
                var extra = userCount < 1 ? "s" : string.Empty;
                UlteriusTray.ShowMessage($"There are now {userCount} user{extra} connected.", "A user disconnected!");
            }
        }

        /// <summary>
        ///     When a client connects, assign them a unique RSA keypair for handshake.
        /// </summary>
        /// <param name="clientSocket"></param>
        private static async void HandleConnect(WebSocket clientSocket)
        {
            var connectionId = CookieManager.GetConnectionId(clientSocket);
            AuthClient authClient;
            AllClients.TryGetValue(connectionId, out authClient);
            var host = new Uri($"ws://{clientSocket.HttpRequest.Headers[RequestHeader.Host]}", UriKind.Absolute);

            if (authClient != null)
            {

                if (RunningAsService)
                {
                    MessageQueueManager agentManager;
                    if (!authClient.MessageQueueManagers.TryGetValue(22005, out agentManager))
                    {
                        if (authClient.MessageQueueManagers.TryAdd(22005,
                            new MessageQueueManager()))
                        {
                            Console.WriteLine("Service Manager Started");
                        }
                    }
                }
                MessageQueueManager manager;
                //check if a manager for that port exist, if not, create one
                
                if (!authClient.MessageQueueManagers.TryGetValue(host.Port, out manager))
                {
                    if (authClient.MessageQueueManagers.TryAdd(host.Port,
                        new MessageQueueManager()))
                    {
                        Console.WriteLine($"Manager started for {host.Port}");
                    }
                }
                return;
            }
            Console.WriteLine("Connection from " + clientSocket.RemoteEndpoint);
            var rsa = new Rsa();
            rsa.GenerateKeyPairs();
            var client = new AuthClient
            {
                PublicKey = rsa.PublicKey,
                PrivateKey = rsa.PrivateKey,
                MessageQueueManagers = new ConcurrentDictionary<int, MessageQueueManager>()
            };
          
            client.MessageQueueManagers.TryAdd(host.Port, new MessageQueueManager());
            AllClients.AddOrUpdate(connectionId, client, (key, value) => value);
            await SendWelcomeMessage(client, clientSocket);
        }

        /// <summary>
        ///     Sends a new user their unique RSA keypair
        /// </summary>
        /// <param name="client"></param>
        /// <param name="clientSocket"></param>
        private static async Task SendWelcomeMessage(AuthClient client, WebSocket clientSocket)
        {
            var welcomeMessage = JsonConvert.SerializeObject(new
            {
                endpoint = "connectedToUlterius",
                results = new
                {
                    message = "Ulterius server online!",
                    publicKey = Rsa.SecureStringToString(client.PublicKey)
                }
            });
            if (clientSocket != null)
            {
                try
                {
                    await clientSocket.WriteStringAsync(welcomeMessage, CancellationToken.None);
                    var userCount = AllClients.Count;
                    var extra = userCount > 1 ? "s" : string.Empty;
                    UlteriusTray.ShowMessage($"There are now {userCount} user{extra} connected.", "A new user connected!");
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Failed to write welcome message " + ex.Message );
                }
            }
        }

        private static void Log(string message)
        {
            Console.WriteLine(message);
        }
    }
namespace UlteriusServer.Api.Win32
        public static extern int GetCurrentThreadId();
﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace UlteriusServer.Api.Win32
{
    public class DesktopWatcher
    {
        private static string _lastDesktop;
        private static Desktop _lastDesktopInput;
        public static void Start()
        {
            var backgroundThread = new Thread(WatchDesktop) { IsBackground = true };
            backgroundThread.Start();
            Console.WriteLine($"Desktop Task is running on thread: {Desktop.GetCurrentThreadId()}");
        }

        private static void WatchDesktop()
        {
            while (true)
            {
                try
                {
                    using (var inputDesktop = new Desktop())
                    {
                        inputDesktop.OpenInput();
                        if (!inputDesktop.DesktopName.Equals(_lastDesktop))
                        {
                            if (inputDesktop.Show() && Desktop.SetCurrent(inputDesktop))
                            {
                               Console.WriteLine($"Desktop switched from {_lastDesktop} to {inputDesktop.DesktopName} on thread {Desktop.GetCurrentThreadId()}");
                                _lastDesktop = inputDesktop.DesktopName;
                                _lastDesktopInput = inputDesktop;
                                CurrentDesktop = inputDesktop;
                            }
                            else
                            {
                                var errorMessage = new Win32Exception(Marshal.GetLastWin32Error()).Message;
                                Console.WriteLine(errorMessage);
                                _lastDesktopInput?.Close();
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message, ex);
                }
                Thread.Sleep(1000);
            }
        }

        public static string CurrentDesktopName { get; set; }

        public static Desktop CurrentDesktop { get; set; }
    }
}
﻿#region

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Runtime.InteropServices;

#endregion

namespace UlteriusServer.Api.Win32
{
    public class Monitor
    {
        public Rectangle Rect { get; set; }
        public Rectangle WorkRect { get; set; }
        public bool Primary { get; set; }
        public string DeviceName { get; set; }
    }

    public class Display
    {

       
        private static IEnumerable<string> GetAllMonitorsFriendlyNames()
        {
            uint pathCount, modeCount;
            var error = GetDisplayConfigBufferSizes(QueryDeviceConfigFlags.QdcOnlyActivePaths, out pathCount,
                out modeCount);
            if (error != ErrorSuccess)
                throw new System.ComponentModel.Win32Exception(error);

            var displayPaths = new DisplayconfigPathInfo[pathCount];
            var displayModes = new DisplayconfigModeInfo[modeCount];
            error = QueryDisplayConfig(QueryDeviceConfigFlags.QdcOnlyActivePaths,
                ref pathCount, displayPaths, ref modeCount, displayModes, IntPtr.Zero);
            if (error != ErrorSuccess)
                throw new System.ComponentModel.Win32Exception(error);

            for (var i = 0; i < modeCount; i++)
                if (displayModes[i].infoType == DisplayconfigModeInfoType.DisplayconfigModeInfoTypeTarget)
                    yield return MonitorFriendlyName(displayModes[i].adapterId, displayModes[i].id);
        }

        public static string GetDeviceFriendlyName(int screenIndex)
        {
            var allFriendlyNames = GetAllMonitorsFriendlyNames().ToList();
            if (screenIndex > allFriendlyNames.Count)
            {
                return null;
            }
            return allFriendlyNames.ElementAtOrDefault(screenIndex) ?? "Unknown";
        }

        private static string MonitorFriendlyName(Luid adapterId, uint targetId)
        {
            var deviceName = new DisplayconfigTargetDeviceName
            {
                header =
                {
                    size = (uint) Marshal.SizeOf(typeof(DisplayconfigTargetDeviceName)),
                    adapterId = adapterId,
                    id = targetId,
                    type = DisplayconfigDeviceInfoType.DisplayconfigDeviceInfoGetTargetName
                }
            };
            var error = DisplayConfigGetDeviceInfo(ref deviceName);
            if (error != ErrorSuccess)
                throw new System.ComponentModel.Win32Exception(error);
            return deviceName.monitorFriendlyDeviceName;
        }

        public const int ErrorSuccess = 0;
        [DllImport("user32.dll")]
        public static extern int GetDisplayConfigBufferSizes(
            QueryDeviceConfigFlags flags, out uint numPathArrayElements, out uint numModeInfoArrayElements);

        [DllImport("user32.dll")]
        public static extern int QueryDisplayConfig(
            QueryDeviceConfigFlags flags,
            ref uint numPathArrayElements, [Out] DisplayconfigPathInfo[] pathInfoArray,
            ref uint numModeInfoArrayElements, [Out] DisplayconfigModeInfo[] modeInfoArray,
            IntPtr currentTopologyId
        );
        [StructLayout(LayoutKind.Sequential)]
        public struct DisplayconfigTargetDeviceNameFlags
        {
            public uint value;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct DisplayconfigDeviceInfoHeader
        {
            public DisplayconfigDeviceInfoType type;
            public uint size;
            public Luid adapterId;
            public uint id;
        }

        public enum DisplayconfigDeviceInfoType : uint
        {
            DisplayconfigDeviceInfoGetSourceName = 1,
            DisplayconfigDeviceInfoGetTargetName = 2,
            DisplayconfigDeviceInfoGetTargetPreferredMode = 3,
            DisplayconfigDeviceInfoGetAdapterName = 4,
            DisplayconfigDeviceInfoSetTargetPersistence = 5,
            DisplayconfigDeviceInfoGetTargetBaseType = 6,
            DisplayconfigDeviceInfoForceUint32 = 0xFFFFFFFF
        }
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        public struct DisplayconfigTargetDeviceName
        {
            public DisplayconfigDeviceInfoHeader header;
            public DisplayconfigTargetDeviceNameFlags flags;
            public DisplayconfigVideoOutputTechnology outputTechnology;
            public ushort edidManufactureId;
            public ushort edidProductCodeId;
            public uint connectorInstance;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string monitorFriendlyDeviceName;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string monitorDevicePath;
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct DisplayconfigModeInfo
        {
            public DisplayconfigModeInfoType infoType;
            public uint id;
            public Luid adapterId;
            public DisplayconfigModeInfoUnion modeInfo;
        }
        [DllImport("user32.dll")]
        public static extern int DisplayConfigGetDeviceInfo(ref DisplayconfigTargetDeviceName deviceName);

        public enum QueryDeviceConfigFlags : uint
        {
            QdcAllPaths = 0x00000001,
            QdcOnlyActivePaths = 0x00000002,
            QdcDatabaseCurrent = 0x00000004
        }
        public enum DisplayconfigModeInfoType : uint
        {
            DisplayconfigModeInfoTypeSource = 1,
            DisplayconfigModeInfoTypeTarget = 2,
            DisplayconfigModeInfoTypeForceUint32 = 0xFFFFFFFF
        }
        [StructLayout(LayoutKind.Explicit)]
        public struct DisplayconfigModeInfoUnion
        {
            [FieldOffset(0)] public DisplayconfigTargetMode targetMode;

            [FieldOffset(0)] public DisplayconfigSourceMode sourceMode;
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct DisplayconfigTargetMode
        {
            public DisplayconfigVideoSignalInfo targetVideoSignalInfo;
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct DisplayconfigPathInfo
        {
            public DisplayconfigPathSourceInfo sourceInfo;
            public DisplayconfigPathTargetInfo targetInfo;
            public uint flags;
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct DisplayconfigSourceMode
        {
            public uint width;
            public uint height;
            public DisplayconfigPixelformat pixelFormat;
            public Pointl position;
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct DisplayconfigPathSourceInfo
        {
            public Luid adapterId;
            public uint id;
            public uint modeInfoIdx;
            public uint statusFlags;
        }

        public static Rectangle GetWindowRectangle()
        {
            var scBounds = new RECT();
            GetWindowRect(GetDesktopWindow(), ref scBounds);
            return scBounds;
        }

        [DllImport("user32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);



        [DllImport("user32.dll", EntryPoint = "GetDesktopWindow")]
        public static extern IntPtr GetDesktopWindow();


        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int Left, Top, Right, Bottom;

            public RECT(int left, int top, int right, int bottom)
            {
                Left = left;
                Top = top;
                Right = right;
                Bottom = bottom;
            }

            public RECT(Rectangle r) : this(r.Left, r.Top, r.Right, r.Bottom)
            {
            }

            public int X
            {
                get => Left;
                set
                {
                    Right -= Left - value;
                    Left = value;
                }
            }

            public int Y
            {
                get => Top;
                set
                {
                    Bottom -= Top - value;
                    Top = value;
                }
            }

            public int Height
            {
                get => Bottom - Top;
                set => Bottom = value + Top;
            }

            public int Width
            {
                get => Right - Left;
                set => Right = value + Left;
            }


            public Size Size
            {
                get => new Size(Width, Height);
                set
                {
                    Width = value.Width;
                    Height = value.Height;
                }
            }

            public static implicit operator Rectangle(RECT r)
            {
                return new Rectangle(r.Left, r.Top, r.Width, r.Height);
            }

            public static implicit operator RECT(Rectangle r)
            {
                return new RECT(r);
            }

            public static bool operator ==(RECT r1, RECT r2)
            {
                return r1.Equals(r2);
            }

            public static bool operator !=(RECT r1, RECT r2)
            {
                return !r1.Equals(r2);
            }

            public bool Equals(RECT r)
            {
                return r.Left == Left && r.Top == Top && r.Right == Right && r.Bottom == Bottom;
            }

            public override bool Equals(object obj)
            {
                if (obj is RECT)
                    return Equals((RECT)obj);
                if (obj is Rectangle)
                    return Equals(new RECT((Rectangle)obj));
                return false;
            }

            public override int GetHashCode()
            {
                return ((Rectangle)this).GetHashCode();
            }

            public override string ToString()
            {
                return string.Format(CultureInfo.CurrentCulture, "{{Left={0},Top={1},Right={2},Bottom={3}}}", Left, Top,
                    Right, Bottom);
            }
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct Displayconfig2Dregion
        {
            public uint cx;
            public uint cy;
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct Pointl
        {
            private readonly int x;
            private readonly int y;
        }
        public enum DisplayconfigPixelformat : uint
        {
            DisplayconfigPixelformat8Bpp = 1,
            DisplayconfigPixelformat16Bpp = 2,
            DisplayconfigPixelformat24Bpp = 3,
            DisplayconfigPixelformat32Bpp = 4,
            DisplayconfigPixelformatNongdi = 5,
            DisplayconfigPixelformatForceUint32 = 0xffffffff
        }
        public struct DisplayconfigVideoSignalInfo
        {
            public ulong pixelRate;
            public DisplayconfigRational hSyncFreq;
            public DisplayconfigRational vSyncFreq;
            public Displayconfig2Dregion activeSize;
            public Displayconfig2Dregion totalSize;
            public uint videoStandard;
            public DisplayconfigScanlineOrdering scanLineOrdering;
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct DisplayconfigPathTargetInfo
        {
            public Luid adapterId;
            public uint id;
            public uint modeInfoIdx;
            private readonly DisplayconfigVideoOutputTechnology outputTechnology;
            private readonly DisplayconfigRotation rotation;
            private readonly DisplayconfigScaling scaling;
            private readonly DisplayconfigRational refreshRate;
            private readonly DisplayconfigScanlineOrdering scanLineOrdering;
            public bool targetAvailable;
            public uint statusFlags;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct Luid
        {
            public uint LowPart;
            public int HighPart;
        }


        public enum DisplayconfigScanlineOrdering : uint
        {
            DisplayconfigScanlineOrderingUnspecified = 0,
            DisplayconfigScanlineOrderingProgressive = 1,
            DisplayconfigScanlineOrderingInterlaced = 2,
            DisplayconfigScanlineOrderingInterlacedUpperfieldfirst = DisplayconfigScanlineOrderingInterlaced,
            DisplayconfigScanlineOrderingInterlacedLowerfieldfirst = 3,
            DisplayconfigScanlineOrderingForceUint32 = 0xFFFFFFFF
        }

        public enum DisplayconfigVideoOutputTechnology : uint
        {
            DisplayconfigOutputTechnologyOther = 0xFFFFFFFF,
            DisplayconfigOutputTechnologyHd15 = 0,
            DisplayconfigOutputTechnologySvideo = 1,
            DisplayconfigOutputTechnologyCompositeVideo = 2,
            DisplayconfigOutputTechnologyComponentVideo = 3,
            DisplayconfigOutputTechnologyDvi = 4,
            DisplayconfigOutputTechnologyHdmi = 5,
            DisplayconfigOutputTechnologyLvds = 6,
            DisplayconfigOutputTechnologyDJpn = 8,
            DisplayconfigOutputTechnologySdi = 9,
            DisplayconfigOutputTechnologyDisplayportExternal = 10,
            DisplayconfigOutputTechnologyDisplayportEmbedded = 11,
            DisplayconfigOutputTechnologyUdiExternal = 12,
            DisplayconfigOutputTechnologyUdiEmbedded = 13,
            DisplayconfigOutputTechnologySdtvdongle = 14,
            DisplayconfigOutputTechnologyMiracast = 15,
            DisplayconfigOutputTechnologyInternal = 0x80000000,
            DisplayconfigOutputTechnologyForceUint32 = 0xFFFFFFFF
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct DisplayconfigRational
        {
            public uint Numerator;
            public uint Denominator;
        }

        public enum DisplayconfigRotation : uint
        {
            DisplayconfigRotationIdentity = 1,
            DisplayconfigRotationRotate90 = 2,
            DisplayconfigRotationRotate180 = 3,
            DisplayconfigRotationRotate270 = 4,
            DisplayconfigRotationForceUint32 = 0xFFFFFFFF
        }

        public enum DisplayconfigScaling : uint
        {
            DisplayconfigScalingIdentity = 1,
            DisplayconfigScalingCentered = 2,
            DisplayconfigScalingStretched = 3,
            DisplayconfigScalingAspectratiocenteredmax = 4,
            DisplayconfigScalingCustom = 5,
            DisplayconfigScalingPreferred = 128,
            DisplayconfigScalingForceUint32 = 0xFFFFFFFF
        }
        public const int MONITORINFOF_PRIMARY = 0x1;
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        public struct MONITORINFOEX
        {
            public int cbSize;
            public RECT rcMonitor;
            public RECT rcWork;
            public int dwFlags;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
            public string szDevice;
        }
        public delegate bool MonitorEnumProc(IntPtr hMonitor, IntPtr hdcMonitor, ref RECT lprcMonitor, IntPtr dwData);
        [DllImport("User32.dll", CharSet = CharSet.Unicode)]
        public static extern bool GetMonitorInfo(IntPtr hMonitor, ref MONITORINFOEX lpmi);

        [DllImport("User32.dll", CharSet = CharSet.Unicode)]
        public static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, MonitorEnumProc lpfnEnum, IntPtr dwData);

        private static List<Monitor> GetMonitors()
        {
            List<Monitor> monitors = new List<Monitor>();

            EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero,
                (IntPtr hMonitor, IntPtr hdcMonitor, ref RECT lprcMonitor, IntPtr dwData) =>
                {
                    MONITORINFOEX monitorInfo = new MONITORINFOEX();
                    monitorInfo.cbSize = Marshal.SizeOf(typeof(MONITORINFOEX));

                    GetMonitorInfo(hMonitor, ref monitorInfo);

                    monitors.Add(new Monitor()
                    {
                        Primary = (monitorInfo.dwFlags & MONITORINFOF_PRIMARY) != 0,
                        DeviceName = monitorInfo.szDevice,
                        Rect = Rectangle.FromLTRB(monitorInfo.rcMonitor.Left,
                            monitorInfo.rcMonitor.Top,
                            monitorInfo.rcMonitor.Right,
                            monitorInfo.rcMonitor.Bottom),
                        WorkRect = Rectangle.FromLTRB(monitorInfo.rcWork.Left,
                            monitorInfo.rcWork.Top,
                            monitorInfo.rcWork.Right,
                            monitorInfo.rcWork.Bottom)
                    });

                    return true;
                },
                IntPtr.Zero
            );

            return monitors;
        }
        public static int X { get; set; }

        public static int Y { get; set; }

        public static int Height { get; set; }

        public static int Width { get; set; }
    }
}
namespace UlteriusServer.Api.Win32.ScreenShare.DesktopDuplication
﻿#region

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using SharpDX;
using SharpDX.Direct3D;
using SharpDX.Direct3D11;
using SharpDX.DXGI;
using SharpDX.Mathematics.Interop;
using Device = SharpDX.Direct3D11.Device;
using MapFlags = SharpDX.Direct3D11.MapFlags;
using Point = System.Drawing.Point;
using Rectangle = SharpDX.Rectangle;
using Resource = SharpDX.DXGI.Resource;
using ResultCode = SharpDX.DXGI.ResultCode;

#endregion

namespace UlteriusServer.Api.Win32.ScreenShare.DesktopDuplication
{
    /// <summary>
    ///     Provides access to frame-by-frame updates of a particular desktop (i.e. one monitor), with image and cursor
    ///     information.
    /// </summary>
    public class DesktopDuplicator
    {
        private readonly OutputDuplication _mDeskDupl;
        private readonly Device _mDevice;
        private readonly Texture2DDescription _mTextureDesc;
        private readonly int _mWhichOutputDevice;
        private Texture2D _desktopImageTexture;

        private Bitmap _finalImage1, _finalImage2;
        private OutputDuplicateFrameInformation _frameInfo;
        private bool _isFinalImage1;
        private OutputDescription _mOutputDesc;

        /// <summary>
        /// Duplicates the output of the specified monitor.
        /// </summary>
        /// <param name="whichMonitor">The output device to duplicate (i.e. monitor). Begins with zero, which seems to correspond to the primary monitor.</param>
        public DesktopDuplicator(int whichMonitor)
            : this(0, whichMonitor) { }

        /// <summary>
        ///     Duplicates the output of the specified monitor on the specified graphics adapter.
        /// </summary>
        /// <param name="whichGraphicsCardAdapter">The adapter which contains the desired outputs.</param>
        /// <param name="whichOutputDevice">
        ///     The output device to duplicate (i.e. monitor). Begins with zero, which seems to
        ///     correspond to the primary monitor.
        /// </param>
        public DesktopDuplicator(int whichGraphicsCardAdapter, int whichOutputDevice)
        {
            _mWhichOutputDevice = whichOutputDevice;
            Adapter1 adapter;
            try
            {
                adapter = new Factory1().GetAdapter1(whichGraphicsCardAdapter);
            }
            catch (SharpDXException)
            {
                throw new DesktopDuplicationException("Could not find the specified graphics card adapter.");
            }
           _mDevice = new Device(adapter);
            Output output = null;
            try
            {
                output = adapter.GetOutput(whichOutputDevice);
            }
            catch (SharpDXException)
            {
                throw new DesktopDuplicationException("Could not find the specified output device.");
            }
            var output1 = output.QueryInterface<Output1>();
            _mOutputDesc = output.Description;
            _mTextureDesc = new Texture2DDescription()
            {
                CpuAccessFlags = CpuAccessFlags.Read,
                BindFlags = BindFlags.None,
                Format = Format.B8G8R8A8_UNorm,
                Width = ((Rectangle)_mOutputDesc.DesktopBounds).Width,
                Height = ((Rectangle)_mOutputDesc.DesktopBounds).Height,
                OptionFlags = ResourceOptionFlags.None,
                MipLevels = 1,
                ArraySize = 1,
                SampleDescription = { Count = 1, Quality = 0 },
                Usage = ResourceUsage.Staging
            };

            try
            {
                _mDeskDupl = output1.DuplicateOutput(_mDevice);
            }
            catch (SharpDXException ex)
            {
                if (ex.ResultCode.Code == ResultCode.NotCurrentlyAvailable.Result.Code)
                {
                    throw new DesktopDuplicationException("There is already the maximum number of applications using the Desktop Duplication API running, please close one of the applications and try again.");
                }
            }
        }

        private Bitmap FinalImage
        {
            get => _isFinalImage1 ? _finalImage1 : _finalImage2;
            set
            {
                if (_isFinalImage1)
                {
                    _finalImage2 = value;
                    _finalImage1?.Dispose();
                }
                else
                {
                    _finalImage1 = value;
                    _finalImage2?.Dispose();
                }
                _isFinalImage1 = !_isFinalImage1;
            }
        }

        /// <summary>
        ///     Finds the most capable graphics card.
        /// </summary>
        /// <returns></returns>
        private static Adapter1 GetBestAdapter(out int bestAdapterIndex)
        {
            using (var dxgiFactory = new Factory1())
            {
                Adapter1 bestAdapter = null;
                bestAdapterIndex = -1;
                var adapterIndex = -1;
                long bestVideoMemory = 0;
                long bestSystemMemory = 0;

                foreach (var dxgiAdapter in dxgiFactory.Adapters1)
                {
                    adapterIndex++;

                    // not skip the render only WARP device
                    if (dxgiAdapter.Description.VendorId != 0x1414 || dxgiAdapter.Description.DeviceId != 0x8c)
                        if (dxgiAdapter.Outputs == null || dxgiAdapter.Outputs.Length == 0)
                            continue;

                    var level = Device.GetSupportedFeatureLevel(dxgiAdapter);

                    if (level < FeatureLevel.Level_11_0)
                        continue;
                    long videoMemory = (uint) dxgiAdapter.Description.DedicatedVideoMemory;
                    long systemMemory = (uint) dxgiAdapter.Description.DedicatedSystemMemory;

                    if (bestAdapter != null && videoMemory <= bestVideoMemory &&
                        (videoMemory != bestVideoMemory || systemMemory <= bestSystemMemory)) continue;
                    bestAdapter = dxgiAdapter;
                    bestAdapterIndex = adapterIndex;
                    bestVideoMemory = videoMemory;
                    bestSystemMemory = systemMemory;
                }

                return bestAdapter;
            }
        }

        /// <summary>
        ///     Retrieves the latest desktop image and associated metadata.
        /// </summary>
        public DesktopFrame GetLatestFrame()
        {
            var frame = new DesktopFrame();
            // Try to get the latest frame; this may timeout
            var retrievalTimedOut = RetrieveFrame();
            if (retrievalTimedOut)
                return null;
            try
            {
                RetrieveFrameMetadata(frame);
                //we don't need cursor info
                //RetrieveCursorMetadata(frame);
                //we dont need a full frame
                //ProcessFrame(frame);
            }
            catch
            {
                ReleaseFrame();
            }
            try
            {
                ReleaseFrame();
            }
            catch
            {
                //    throw new DesktopDuplicationException("Couldn't release frame.");  
            }
            return frame;
        }

        private bool RetrieveFrame()
        {
            if (_desktopImageTexture == null)
                _desktopImageTexture = new Texture2D(_mDevice, _mTextureDesc);
            Resource desktopResource = null;
            _frameInfo = new OutputDuplicateFrameInformation();
            try
            {
                _mDeskDupl.AcquireNextFrame(500, out _frameInfo, out desktopResource);
            }
            catch (SharpDXException ex)
            {
                if (ex.ResultCode.Code == ResultCode.WaitTimeout.Result.Code)
                    return true;
                if (ex.ResultCode.Failure)
                {
                    //return true;
                    desktopResource?.Dispose();
                    throw new DesktopDuplicationException("Failed to acquire next frame.");
                }
            }
            using (var tempTexture = desktopResource?.QueryInterface<Texture2D>())
            {
                _mDevice.ImmediateContext.CopyResource(tempTexture, _desktopImageTexture);
            }
            desktopResource?.Dispose();
            return false;
        }

        private void RetrieveFrameMetadata(DesktopFrame frame)
        {
            if (_frameInfo.TotalMetadataBufferSize > 0)
            {
                // Get moved regions
                var movedRegionsLength = 0;
                var movedRectangles = new OutputDuplicateMoveRectangle[_frameInfo.TotalMetadataBufferSize];
                _mDeskDupl.GetFrameMoveRects(movedRectangles.Length, movedRectangles, out movedRegionsLength);
                frame.MovedRegions =
                    new MovedRegion[movedRegionsLength / Marshal.SizeOf(typeof(OutputDuplicateMoveRectangle))];
                for (var i = 0; i < frame.MovedRegions.Length; i++)
                {
                    var destRect = (Rectangle) movedRectangles[i].DestinationRect;
                    frame.MovedRegions[i] = new MovedRegion
                    {
                        Source = new Point(movedRectangles[i].SourcePoint.X, movedRectangles[i].SourcePoint.Y),
                        Destination =
                            new System.Drawing.Rectangle(destRect.X, destRect.Y, destRect.Width, destRect.Height)
                    };
                }

                // Get dirty regions
                var dirtyRegionsLength = 0;
                var dirtyRectangles = new RawRectangle[_frameInfo.TotalMetadataBufferSize];
                _mDeskDupl.GetFrameDirtyRects(dirtyRectangles.Length, dirtyRectangles, out dirtyRegionsLength);
                frame.UpdatedRegions =
                    new System.Drawing.Rectangle[dirtyRegionsLength / Marshal.SizeOf(typeof(Rectangle))];
                frame.FinishedRegions = new FinishedRegions[frame.UpdatedRegions.Length];
                for (var i = 0; i < frame.UpdatedRegions.Length; i++)
                {
                    var dirtyRect = (Rectangle) dirtyRectangles[i];
                    var rect = new System.Drawing.Rectangle(dirtyRect.X, dirtyRect.Y, dirtyRect.Width,
                        dirtyRect.Height);


                    frame.FinishedRegions[i] = new FinishedRegions
                    {
                        Destination = rect,
                        Frame = ExtractRect(rect.X, rect.Y, rect.Width, rect.Height)
                    };
                }
            }
            else
            {
                frame.MovedRegions = new MovedRegion[0];
                frame.UpdatedRegions = new System.Drawing.Rectangle[0];
            }
        }


        private Bitmap ExtractRect(int originX, int originY, int width, int height)
        {
            // Get the desktop capture screenTexture
            var mapSource = _mDevice.ImmediateContext.MapSubresource(_desktopImageTexture, 0, MapMode.Read,
                MapFlags.None);

            // Create Drawing.Bitmap

            var bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); //不能是ARGB
            var boundsRect = new System.Drawing.Rectangle(0, 0, width, height);

            // Copy pixels from screen capture Texture to GDI bitmap
            var mapDest = bitmap.LockBits(boundsRect, ImageLockMode.WriteOnly, bitmap.PixelFormat);
            var sourcePtr = mapSource.DataPointer;
            var destPtr = mapDest.Scan0;

            sourcePtr = IntPtr.Add(sourcePtr, originY * mapSource.RowPitch + originX * 4);
            for (var y = 0; y < height; y++)
            {
                // Copy a single line 

                SharpDX.Utilities.CopyMemory(destPtr, sourcePtr, width * 4);

                // Advance pointers
                if (y != height - 1)
                    sourcePtr = IntPtr.Add(sourcePtr, mapSource.RowPitch);
                destPtr = IntPtr.Add(destPtr, mapDest.Stride);
            }

            // Release source and dest locks
            bitmap.UnlockBits(mapDest);
            _mDevice.ImmediateContext.UnmapSubresource(_desktopImageTexture, 0);
            return bitmap;
        }

        private void ProcessFrame(DesktopFrame frame)
        {
            // Get the desktop capture texture
            var mapSource = _mDevice.ImmediateContext.MapSubresource(_desktopImageTexture, 0, MapMode.Read,
                MapFlags.None);
            var bounds = (Rectangle) _mOutputDesc.DesktopBounds;
            FinalImage = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format32bppArgb);
            var boundsRect = new System.Drawing.Rectangle(0, 0, bounds.Width, bounds.Height);
            // Copy pixels from screen capture Texture to GDI bitmap
            var mapDest = FinalImage.LockBits(boundsRect, ImageLockMode.WriteOnly, FinalImage.PixelFormat);
            var sourcePtr = mapSource.DataPointer;
            var destPtr = mapDest.Scan0;
            for (var y = 0; y < bounds.Height; y++)
            {
                // Copy a single line 
                SharpDX.Utilities.CopyMemory(destPtr, sourcePtr, bounds.Width * 4);

                // Advance pointers
                sourcePtr = IntPtr.Add(sourcePtr, mapSource.RowPitch);
                destPtr = IntPtr.Add(destPtr, mapDest.Stride);
            }

            // Release source and dest locks
            FinalImage.UnlockBits(mapDest);
            _mDevice.ImmediateContext.UnmapSubresource(_desktopImageTexture, 0);
            frame.DesktopImage = (Bitmap) FinalImage.Clone();
        }

        private void ReleaseFrame()
        {
            try
            {
                _mDeskDupl.ReleaseFrame();
            }
            catch (SharpDXException ex)
            {
                if (ex.ResultCode.Failure)
                    throw new DesktopDuplicationException("Failed to release frame.");
            }
        }
    }
namespace UlteriusServer.Api.Win32.ScreenShare.DesktopDuplication
﻿using System.Drawing;
namespace UlteriusServer.Api.Win32.ScreenShare.DesktopDuplication
namespace UlteriusServer.Api.Win32.ScreenShare.DesktopDuplication
namespace UlteriusServer.Api.Win32.ScreenShare.Models
using UlteriusServer.Api.Win32.ScreenShare.DesktopDuplication;
namespace UlteriusServer.Api.Win32.ScreenShare.Models
    
      
      
    

﻿namespace UlteriusServer.Api.Win32.ScreenShare.Models
using UlteriusServer.Api.Win32.ScreenShare.DesktopDuplication;
using UlteriusServer.Api.Win32.ScreenShare.Models;
using UlteriusServer.Utilities;
namespace UlteriusServer.Api.Win32.ScreenShare
                _desktopDuplicator = new DesktopDuplicator(0);
                _desktopDuplicator = new DesktopDuplicator(0);
                Console.WriteLine("desktop duplication failed");
namespace UlteriusServer.Api.Win32
namespace UlteriusServer.Api.Win32
namespace UlteriusServer.Api.Win32
namespace UlteriusServer.Api.Win32
﻿<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    
  </configSections>
  <system.net>
    <settings>
      <httpWebRequest useUnsafeHeaderParsing="true" />
    </settings>
  </system.net>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
  </startup>
  <runtime>
    <loadFromRemoteSources enabled="true" />
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="AForge.Video" publicKeyToken="cbfb6e07d173c401" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-2.2.5.0" newVersion="2.2.5.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Magnum" publicKeyToken="b800c4cfcdeea87b" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-2.1.3.0" newVersion="2.1.3.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="vtortola.WebSockets" publicKeyToken="7f78616efb4a208d" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-2.2.1.0" newVersion="2.2.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="vtortola.WebSockets.Rfc6455" publicKeyToken="7f78616efb4a208d" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-2.2.1.0" newVersion="2.2.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="vtortola.WebSockets.Deflate" publicKeyToken="7f78616efb4a208d" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-2.2.1.0" newVersion="2.2.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="AForge" publicKeyToken="c1db6ff4eaa06aeb" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-2.2.5.0" newVersion="2.2.5.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Threading.Tasks.Dataflow" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.6.2.0" newVersion="4.6.2.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="SharpDX" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.2.0" newVersion="3.0.2.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="SharpDX.DXGI" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.2.0" newVersion="3.0.2.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="v13.0" />
      </parameters>
    </defaultConnectionFactory>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
      <provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
    </providers>
  </entityFramework>
  
                if (Process.GetProcessesByName(Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location))
                        .Count() > 1)
                    return;
                if (!Directory.Exists(AppEnvironment.DataPath))
                    Directory.CreateDirectory(AppEnvironment.DataPath);
                if (!Debugger.IsAttached)
                {
                    ExceptionHandler.AddGlobalHandlers();
                    Console.WriteLine("Exception Handlers Attached");
                }
                ProfileOptimization.SetProfileRoot(AppEnvironment.DataPath);
                ProfileOptimization.StartProfile("Startup.Profile");
                var ulterius = new Ulterius();
                ulterius.Start();
                Console.ReadKey();
[assembly: AssemblyVersion("1.9.5.0")]
[assembly: AssemblyFileVersion("1.9.5.0")]
using UlteriusServer.Utilities;
using ILogger = UlteriusServer.TerminalServer.Infrastructure.ILogger;
              
                    _ws.CloseAsync();
using ILogger = UlteriusServer.TerminalServer.Infrastructure.ILogger;
            var options = new WebSocketListenerOptions
                HttpAuthenticationHandler = this.HttpNegotiation
            };
            options.Standards.RegisterRfc6455();
            _wsServer = new WebSocketListener(endpoint, options);
            _wsServer.StartAsync().GetAwaiter().GetResult();
        private async Task<bool> HttpNegotiation(WebSocketHttpRequest request, WebSocketHttpResponse response)
            await Task.Delay(TimeSpan.FromMilliseconds(1));
                       
            return true;
                   // _log.Error("Error Accepting clients", aex.GetBaseException());
           
            //_log.Info("Server Stop accepting clients");
using UlteriusServer.Api.Win32;
            Tools.RestartDaemon();
             var settings = Config.Load();
            if (UlteriusApiServer.RunningAsService)
            {
                Console.Write($"Service: {UlteriusApiServer.RunningAsService}");
                DesktopWatcher.Start();
            }
﻿<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="..\packages\Microsoft.Net.Compilers.2.4.0\build\Microsoft.Net.Compilers.props" Condition="Exists('..\packages\Microsoft.Net.Compilers.2.4.0\build\Microsoft.Net.Compilers.props')" />
  <Import Project="..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.3\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props" Condition="Exists('..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.3\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" />
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{E9A365D5-AEBE-4AF3-86C5-D17BC65ADE46}</ProjectGuid>
    <OutputType>Exe</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>UlteriusServer</RootNamespace>
    <AssemblyName>Ulterius Server</AssemblyName>
    <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
    <NuGetPackageImportStamp>
    </NuGetPackageImportStamp>
    <TargetFrameworkProfile />
    <IsWebBootstrapper>false</IsWebBootstrapper>
    <PublishUrl>publish\</PublishUrl>
    <Install>true</Install>
    <InstallFrom>Disk</InstallFrom>
    <UpdateEnabled>false</UpdateEnabled>
    <UpdateMode>Foreground</UpdateMode>
    <UpdateInterval>7</UpdateInterval>
    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
    <UpdatePeriodically>false</UpdatePeriodically>
    <UpdateRequired>false</UpdateRequired>
    <MapFileExtensions>true</MapFileExtensions>
    <ApplicationRevision>0</ApplicationRevision>
    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
    <UseApplicationTrust>false</UseApplicationTrust>
    <BootstrapperEnabled>true</BootstrapperEnabled>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <Prefer32Bit>false</Prefer32Bit>
    <LangVersion>7</LangVersion>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <LangVersion>7</LangVersion>
    <Prefer32Bit>false</Prefer32Bit>
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
  </PropertyGroup>
  <PropertyGroup />
  <PropertyGroup />
  <PropertyGroup />
  <PropertyGroup>
    <ApplicationManifest>app.manifest</ApplicationManifest>
  </PropertyGroup>
  <PropertyGroup>
    <ApplicationIcon>256.ico</ApplicationIcon>
  </PropertyGroup>
  <PropertyGroup>
    <StartupObject />
  </PropertyGroup>
  <PropertyGroup>
    <SignAssembly>false</SignAssembly>
  </PropertyGroup>
  <PropertyGroup>
    <AssemblyOriginatorKeyFile>
    </AssemblyOriginatorKeyFile>
  </PropertyGroup>
  <PropertyGroup>
    <SignManifests>false</SignManifests>
  </PropertyGroup>
  <ItemGroup>
    <Compile Include="Api\Network\Messages\MessageResolver.cs" />
    <Compile Include="Api\Network\Messages\PacketLoader.cs" />
    <Compile Include="Api\Network\Messages\RectangleConverter.cs" />
    <Compile Include="Api\Network\Models\FanInformation.cs" />
    <Compile Include="Api\Network\Models\LoginInformation.cs" />
    <Compile Include="Api\Network\PacketHandlers\DisplayPacketHandler.cs" />
    <Compile Include="Api\Services\LocalSystem\Daemons\JobModel.cs" />
    <Compile Include="Api\Network\PacketHandlers\CronJobPacketHandler.cs" />
    <Compile Include="Api\Services\LocalSystem\Daemons\CronDaemon.cs" />
    <Compile Include="Api\Services\LocalSystem\Daemons\CronJob.cs" />
    <Compile Include="Api\Services\LocalSystem\Daemons\CronSchedule.cs" />
    <Compile Include="Api\Services\LocalSystem\CronJobService.cs" />
    <Compile Include="Api\Services\Update\UpdateService.cs" />
    <Compile Include="Api\Network\Messages\Message.cs" />
    <Compile Include="Api\Network\Messages\MessageQueueManager.cs" />
    <Compile Include="Api\Services\LocalSystem\FileSearchService.cs" />
    <Compile Include="Api\SystemData.cs" />
    <Compile Include="Api\Win32\Desktop.cs" />
    <Compile Include="Api\Win32\DesktopWatcher.cs" />
    <Compile Include="Api\Win32\Display.cs" />
    <Compile Include="Api\Win32\ScreenShare\DesktopDuplication\DesktopDuplicationException.cs" />
    <Compile Include="Api\Win32\ScreenShare\DesktopDuplication\DesktopDuplicator.cs" />
    <Compile Include="Api\Win32\ScreenShare\DesktopDuplication\DesktopFrame.cs" />
    <Compile Include="Api\Win32\ScreenShare\DesktopDuplication\FinishedRegions.cs" />
    <Compile Include="Api\Win32\ScreenShare\DesktopDuplication\MovedRegion.cs" />
    <Compile Include="Api\Win32\ScreenShare\Models\DisplayInformation.cs" />
    <Compile Include="Api\Win32\ScreenShare\Models\FrameInformation.cs" />
    <Compile Include="Api\Win32\ScreenShare\Models\ResolutionInformation.cs" />
    <Compile Include="Api\Win32\ScreenShare\ScreenData.cs" />
    <Compile Include="Api\Win32\SessionInfo.cs" />
    <Compile Include="Api\Win32\Win32Exception.cs" />
    <Compile Include="Api\Win32\WinApi.cs" />
    <Compile Include="Api\Win32\WindowsIdentityImpersonator.cs" />
    <Compile Include="Forms\Utilities\AboutBox.cs">
      <SubType>Form</SubType>
    </Compile>
    <Compile Include="Forms\Utilities\AboutBox.Designer.cs">
      <DependentUpon>AboutBox.cs</DependentUpon>
    </Compile>
    <Compile Include="TerminalServer\Infrastructure\ILogger.cs" />
    <Compile Include="TerminalServer\Infrastructure\Log4NetLogger.cs" />
    <Compile Include="Ulterius.cs" />
    <Compile Include="Utilities\AppEnvironment.cs" />
    <Compile Include="Utilities\Config.cs" />
    <Compile Include="Utilities\Drive\PartitionModel.cs" />
    <Compile Include="Utilities\Drive\SmartData.cs" />
    <Compile Include="Utilities\Drive\SmartEnums.cs" />
    <Compile Include="Utilities\Drive\SmartModel.cs" />
    <Compile Include="Utilities\Extensions\NetworkBrowser.cs" />
    <Compile Include="Utilities\Extensions\ProcessExtensions.cs" />
    <Compile Include="Utilities\Extensions\TaskExtensions.cs" />
    <Compile Include="Utilities\Files\Database\DatabaseController.cs" />
    <Compile Include="Utilities\Files\Database\DatabaseManager.cs" />
    <Compile Include="Utilities\Security\Streams\OfbStream.cs" />
    <Compile Include="Utilities\Security\Streams\ZeroStream.cs" />
    <Compile Include="Utilities\Security\AuthUtils.cs" />
    <Compile Include="WebCams\WebCamManager.cs" />
    <Compile Include="WebSocketAPI\Authentication\AuthClient.cs" />
    <Compile Include="Forms\Utilities\UlteriusTray.cs" />
    <Compile Include="Api\Network\Messages\Packet.cs" />
    <Compile Include="Api\Network\Messages\MessageBuilder.cs" />
    <Compile Include="Api\Network\PacketHandler.cs" />
    <Compile Include="Api\Network\PacketHandlers\ErrorPacketHandler.cs" />
    <Compile Include="Api\Network\PacketManager.cs" />
    <Compile Include="Api\Network\PacketHandlers\WebCamPacketHandler.cs" />
    <Compile Include="Api\Network\PacketHandlers\FilePacketHandler.cs" />
    <Compile Include="Api\Network\PacketHandlers\GpuPacketHandler.cs" />
    <Compile Include="Api\Network\PacketHandlers\ScreenSharePacketHandler.cs" />
    <Compile Include="Api\Network\PacketHandlers\AccountPacketHandler.cs" />
    <Compile Include="Api\Network\PacketHandlers\SettingsPacketHandler.cs" />
    <Compile Include="Api\Network\PacketHandlers\NetworkPacketHandler.cs" />
    <Compile Include="Api\Network\PacketHandlers\CpuPacketHandler.cs" />
    <Compile Include="Api\Network\PacketHandlers\OperatingSystemPacketHandler.cs" />
    <Compile Include="Api\Network\PacketHandlers\ProcessPacketHandler.cs" />
    <Compile Include="Api\Network\PacketHandlers\ServerPacketHandler.cs" />
    <Compile Include="Api\Network\PacketHandlers\SystemPacketHandler.cs" />
    <Compile Include="Api\Network\Models\GpuInformation.cs" />
    <Compile Include="Api\Services\LocalSystem\ScreenShareService.cs" />
    <Compile Include="TerminalServer\Cli\CommandSession.cs" />
    <Compile Include="TerminalServer\Cli\PowerShellSession.cs" />
    <Compile Include="TerminalServer\Cli\_ICliSession.cs" />
    <Compile Include="TerminalServer\Cli\_ICliSessionFactory.cs" />
    <Compile Include="TerminalServer\Infrastructure\SystemInfo.cs" />
    <Compile Include="TerminalServer\Infrastructure\_ISystemInfo.cs" />
    <Compile Include="TerminalServer\Messaging\Connection\ConnectionConnectRequest.cs" />
    <Compile Include="TerminalServer\Messaging\Connection\IConnectionEvent.cs" />
    <Compile Include="TerminalServer\Messaging\Connection\IConnectionRequest.cs" />
    <Compile Include="TerminalServer\Messaging\IMessageBus.cs" />
    <Compile Include="TerminalServer\Messaging\Serialization\DefaultEventSerializator.cs" />
    <Compile Include="TerminalServer\Messaging\Serialization\IEventSerializator.cs" />
    <Compile Include="TerminalServer\Messaging\TerminalControl\Events\ClosedTerminalEvent.cs" />
    <Compile Include="TerminalServer\Messaging\TerminalControl\Events\CreatedTerminalEvent.cs" />
    <Compile Include="TerminalServer\Messaging\TerminalControl\Events\SessionStateEvent.cs" />
    <Compile Include="TerminalServer\Messaging\TerminalControl\Events\TerminalOutputEvent.cs" />
    <Compile Include="TerminalServer\Messaging\TerminalControl\Events\_ITerminalEvent.cs" />
    <Compile Include="TerminalServer\Messaging\TerminalControl\Handlers\AesHandshakeRequestHandler.cs" />
    <Compile Include="TerminalServer\Messaging\TerminalControl\Handlers\CloseTerminalRequestHandler.cs" />
    <Compile Include="TerminalServer\Messaging\TerminalControl\Handlers\CreateTerminalRequestHandler.cs" />
    <Compile Include="TerminalServer\Messaging\TerminalControl\Handlers\InputTerminalRequestHandler.cs" />
    <Compile Include="TerminalServer\Messaging\TerminalControl\Handlers\_IRequestHandler.cs" />
    <Compile Include="TerminalServer\Messaging\TerminalControl\Requests\AesHandshakeRequest.cs" />
    <Compile Include="TerminalServer\Messaging\TerminalControl\Requests\CloseTerminalRequest.cs" />
    <Compile Include="TerminalServer\Messaging\TerminalControl\Requests\CreateTerminalRequest.cs" />
    <Compile Include="TerminalServer\Messaging\TerminalControl\Requests\TerminalInputRequest.cs" />
    <Compile Include="TerminalServer\Messaging\TerminalControl\Requests\_TerminalControlRequest.cs" />
    <Compile Include="TerminalServer\Messaging\WebSocketHandler.cs" />
    <Compile Include="TerminalServer\Messaging\WebSocketQueueServer.cs" />
    <Compile Include="TerminalServer\Session\ConnectionManager.cs" />
    <Compile Include="TerminalServer\Session\UserConnection.cs" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Api\UlteriusApiServer.cs" />
    <Compile Include="TerminalServer\TerminalManagerServer.cs" />
    <Compile Include="Utilities\DynamicMap.cs" />
    <Compile Include="Utilities\Extensions\StringExtensions.cs" />
    <Compile Include="Utilities\Files\FileManager.cs" />
    <Compile Include="Utilities\IconTools.cs" />
    <Compile Include="Utilities\Security\UlteriusAes.cs" />
    <Compile Include="Utilities\Security\Rsa.cs" />
    <Compile Include="Utilities\Files\FileTree.cs" />
    <Compile Include="Utilities\Trace.cs" />
    <Compile Include="WebServer\MultipartParser.cs" />
    <Compile Include="WebSocketAPI\Authentication\CookieManager.cs" />
    <Compile Include="WebSocketAPI\WebSocketEventListener.cs" />
    <Compile Include="Api\Network\Models\DriveInformation.cs" />
    <Compile Include="Api\Network\Models\SystemInformation.cs" />
    <Compile Include="Api\Network\Models\NetworkInformation.cs" />
    <Compile Include="Api\Network\Models\CpuInformation.cs" />
    <Compile Include="Api\Network\Models\OperatingSystemInformation.cs" />
    <Compile Include="Program.cs" />
    <Compile Include="Properties\Resources.Designer.cs">
      <AutoGen>True</AutoGen>
      <DesignTime>True</DesignTime>
      <DependentUpon>Resources.resx</DependentUpon>
    </Compile>
    <Compile Include="Api\Network\Models\ProcessInformation.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
    <Compile Include="Utilities\ExceptionHandler.cs" />
    <Compile Include="Api\Services\Network\NetworkService.cs" />
    <Compile Include="Api\Services\LocalSystem\SystemService.cs" />
    <Compile Include="Utilities\Tools.cs" />
    <Compile Include="WebServer\HttpServer.cs" />
  </ItemGroup>
  <ItemGroup>
    <None Include="App.config" />
    <None Include="app.manifest" />
    <None Include="App1.config" />
    <None Include="packages.config" />
  </ItemGroup>
  <ItemGroup>
    <EmbeddedResource Include="Forms\Utilities\AboutBox.resx">
      <DependentUpon>AboutBox.cs</DependentUpon>
    </EmbeddedResource>
    <EmbeddedResource Include="Properties\Resources.resx">
      <Generator>ResXFileCodeGenerator</Generator>
      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
      <SubType>Designer</SubType>
    </EmbeddedResource>
  </ItemGroup>
  <ItemGroup>
    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
      <Visible>False</Visible>
      <ProductName>.NET Framework 3.5 SP1</ProductName>
      <Install>false</Install>
    </BootstrapperPackage>
  </ItemGroup>
  <ItemGroup>
    <Content Include="256.ico" />
    <EmbeddedResource Include="Packets.json" />
    <None Include="Resources\ApplicationIcon.ico" />
    <Content Include="twitter-profile.ico" />
  </ItemGroup>
  <ItemGroup>
    <WCFMetadata Include="Service References\" />
  </ItemGroup>
  <ItemGroup>
    <Folder Include="bin\Debug\" />
    <Folder Include="Utilities\Files\Models\" />
  </ItemGroup>
  <ItemGroup>
    <Reference Include="AForge, Version=2.2.5.0, Culture=neutral, PublicKeyToken=c1db6ff4eaa06aeb, processorArchitecture=MSIL">
      <HintPath>..\packages\AForge.2.2.5\lib\AForge.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="AForge.Imaging, Version=2.2.5.0, Culture=neutral, PublicKeyToken=ba8ddea9676ca48b, processorArchitecture=MSIL">
      <HintPath>..\packages\AForge.Imaging.2.2.5\lib\AForge.Imaging.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="AForge.Math, Version=2.2.5.0, Culture=neutral, PublicKeyToken=abba2e25397ee8c9, processorArchitecture=MSIL">
      <HintPath>..\packages\AForge.Math.2.2.5\lib\AForge.Math.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="AForge.Video, Version=2.2.5.0, Culture=neutral, PublicKeyToken=cbfb6e07d173c401, processorArchitecture=MSIL">
      <HintPath>..\packages\AForge.Video.2.2.5\lib\AForge.Video.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="AForge.Video.DirectShow, Version=2.2.5.0, Culture=neutral, PublicKeyToken=61ea4348d43881b7, processorArchitecture=MSIL">
      <HintPath>..\packages\AForge.Video.DirectShow.2.2.5\lib\AForge.Video.DirectShow.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="AForge.Vision, Version=2.2.5.0, Culture=neutral, PublicKeyToken=b612fa915eefaa06, processorArchitecture=MSIL">
      <HintPath>..\packages\AForge.Vision.2.2.5\lib\AForge.Vision.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="BouncyCastle.Crypto, Version=1.8.1.0, Culture=neutral, PublicKeyToken=0e99375e54769942">
      <HintPath>..\packages\BouncyCastle.1.8.1\lib\BouncyCastle.Crypto.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="deniszykov.WebSocketListener, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7f78616efb4a208d, processorArchitecture=MSIL">
      <HintPath>..\packages\deniszykov.WebSocketListener.4.0.0\lib\net45\deniszykov.WebSocketListener.dll</HintPath>
    </Reference>
    <Reference Include="DotNetZip, Version=1.10.1.0, Culture=neutral, PublicKeyToken=6583c7c814667745, processorArchitecture=MSIL">
      <HintPath>..\packages\DotNetZip.1.10.1\lib\net20\DotNetZip.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
      <HintPath>..\packages\log4net.2.0.8\lib\net45-full\log4net.dll</HintPath>
    </Reference>
    <Reference Include="Magnum, Version=2.1.3.0, Culture=neutral, PublicKeyToken=b800c4cfcdeea87b, processorArchitecture=MSIL">
      <HintPath>..\packages\Magnum.2.1.3\lib\NET40\Magnum.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="MassTransit, Version=2.9.0.0, Culture=neutral, PublicKeyToken=b8e0e9f2f1e657fa, processorArchitecture=MSIL">
      <HintPath>..\packages\MassTransit.2.9.0\lib\net40\MassTransit.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
      <HintPath>..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.3\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="MiscUtil, Version=0.2.0.0, Culture=neutral, PublicKeyToken=d3c42c4bfacf7596, processorArchitecture=MSIL">
      <HintPath>..\packages\JonSkeet.MiscUtil.0.2.0\lib\net35\MiscUtil.dll</HintPath>
    </Reference>
    <Reference Include="Mono.Cecil, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
      <HintPath>..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="Mono.Cecil.Mdb, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
      <HintPath>..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Mdb.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="Mono.Cecil.Pdb, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
      <HintPath>..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Pdb.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="Mono.Cecil.Rocks, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
      <HintPath>..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Rocks.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
      <HintPath>..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
    </Reference>
    <Reference Include="Open.Nat, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f22a6a4582336c76, processorArchitecture=MSIL">
      <HintPath>..\packages\Open.NAT.2.1.0.0\lib\net45\Open.Nat.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="OpenHardwareMonitorLib">
      <HintPath>..\Deps\OpenHardwareMonitorLib.dll</HintPath>
    </Reference>
    <Reference Include="PresentationCore" />
    <Reference Include="SharpDX, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
      <HintPath>..\packages\SharpDX.4.0.1\lib\net45\SharpDX.dll</HintPath>
    </Reference>
    <Reference Include="SharpDX.Direct3D11, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
      <HintPath>..\packages\SharpDX.Direct3D11.4.0.1\lib\net45\SharpDX.Direct3D11.dll</HintPath>
    </Reference>
    <Reference Include="SharpDX.DXGI, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
      <HintPath>..\packages\SharpDX.DXGI.4.0.1\lib\net45\SharpDX.DXGI.dll</HintPath>
    </Reference>
    <Reference Include="SharpDX.Mathematics, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
      <HintPath>..\packages\SharpDX.Mathematics.4.0.1\lib\net45\SharpDX.Mathematics.dll</HintPath>
    </Reference>
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="System.DirectoryServices" />
    <Reference Include="System.DirectoryServices.AccountManagement" />
    <Reference Include="System.Drawing" />
    <Reference Include="System.IO.Compression" />
    <Reference Include="System.Management" />
    <Reference Include="System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\3.0\System.Management.Automation.dll</HintPath>
    </Reference>
    <Reference Include="System.Net" />
    <Reference Include="System.Net.Http" />
    <Reference Include="System.ServiceModel" />
    <Reference Include="System.ServiceProcess" />
    <Reference Include="System.Threading.Tasks.Dataflow, Version=4.6.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
      <HintPath>..\packages\System.Threading.Tasks.Dataflow.4.8.0\lib\netstandard2.0\System.Threading.Tasks.Dataflow.dll</HintPath>
    </Reference>
    <Reference Include="System.Web" />
    <Reference Include="System.Windows.Forms" />
    <Reference Include="System.Xaml" />
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System.Xml" />
    <Reference Include="Topshelf, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b800c4cfcdeea87b, processorArchitecture=MSIL">
      <HintPath>..\packages\Topshelf.4.0.3\lib\net452\Topshelf.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="TurboJpegWrapper, Version=1.4.2.19498, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\packages\TurboJpegWrapper.1.4.2.6\lib\net35\TurboJpegWrapper.dll</HintPath>
    </Reference>
    <Reference Include="WindowsBase" />
    <Reference Include="ZetaLongPaths, Version=1.0.0.19, Culture=neutral, PublicKeyToken=b764f59068f31f38, processorArchitecture=MSIL">
      <HintPath>..\packages\ZetaLongPaths.1.0.0.19\lib\net40-full\ZetaLongPaths.dll</HintPath>
    </Reference>
  </ItemGroup>
  <ItemGroup>
    <COMReference Include="NetFwTypeLib">
      <Guid>{58FBCF7C-E7A9-467C-80B3-FC65E8FCCA08}</Guid>
      <VersionMajor>1</VersionMajor>
      <VersionMinor>0</VersionMinor>
      <Lcid>0</Lcid>
      <WrapperTool>tlbimp</WrapperTool>
      <Isolated>False</Isolated>
      <EmbedInteropTypes>True</EmbedInteropTypes>
    </COMReference>
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\..\..\..\inputsimulator2\WindowsInput\WindowsInput.csproj">
      <Project>{3549cd6f-80f8-450f-b99e-cf0a736b1f2a}</Project>
      <Name>WindowsInput</Name>
    </ProjectReference>
    <ProjectReference Include="..\UlteriusAgent\UlteriusAgent.csproj">
      <Project>{686ae4c4-791f-45eb-9414-029d6115905d}</Project>
      <Name>UlteriusAgent</Name>
    </ProjectReference>
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
    <PropertyGroup>
      <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
    </PropertyGroup>
    <Error Condition="!Exists('..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.3\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.3\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props'))" />
    <Error Condition="!Exists('..\packages\TurboJpegWrapper.1.4.2.6\build\TurboJpegWrapper.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\TurboJpegWrapper.1.4.2.6\build\TurboJpegWrapper.targets'))" />
    <Error Condition="!Exists('..\packages\Microsoft.Net.Compilers.2.4.0\build\Microsoft.Net.Compilers.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Net.Compilers.2.4.0\build\Microsoft.Net.Compilers.props'))" />
  </Target>
  <PropertyGroup>
    <PostBuildEvent>
    </PostBuildEvent>
  </PropertyGroup>
  <PropertyGroup>
    <PreBuildEvent>
    </PreBuildEvent>
  </PropertyGroup>
  <Target Name="AfterClean">
    <Delete Files="$(TargetDir)\*.dll" />
  </Target>
  <Target Name="AfterClean">
    <ItemGroup>
      <FilesToDelete Include="$(TargetDir)\*.dll" />
    </ItemGroup>
    <Delete Files="@(FilesToDelete)" />
  </Target>
﻿<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
	<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp70</s:String></wpf:ResourceDictionary>
namespace UlteriusServer.Utilities
namespace UlteriusServer.Utilities
﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Management;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;

namespace UlteriusServer.Utilities.Extensions
{
    public static class ProcessExtensions
    {
        [DllImport("user32.dll")]
        public static extern IntPtr FindWindowEx(IntPtr parentWindow, IntPtr previousChildWindow, string windowClass,
            string windowTitle);

        [DllImport("user32.dll")]
        private static extern IntPtr GetWindowThreadProcessId(IntPtr window, out int process);

        public static IntPtr[] GetProcessWindows(this Process process)
        {
            var apRet = new IntPtr[256];
            var iCount = 0;
            var pLast = IntPtr.Zero;
            do
            {
                pLast = FindWindowEx(IntPtr.Zero, pLast, null, null);
                int iProcess_;
                GetWindowThreadProcessId(pLast, out iProcess_);
                if (iProcess_ == process.Id)
                {
                    apRet[iCount++] = pLast;
                }
            } while (pLast != IntPtr.Zero);
            Array.Resize(ref apRet, iCount);
            return apRet;
        }

        private static string FindIndexedProcessName(int pid)
        {
            try
            {
                var processName = Process.GetProcessById(pid).ProcessName;
                var processesByName = Process.GetProcessesByName(processName);
                string processIndexdName = null;
                for (var index = 0; index < processesByName.Length; index++)
                {
                    processIndexdName = index == 0 ? processName : processName + "#" + index;
                    var processId = new PerformanceCounter("Process", "ID Process", processIndexdName);
                    if ((int)processId.NextValue() == pid)
                    {
                        return processIndexdName;
                    }
                }
                return processIndexdName;
            }
            catch (Exception)
            {
                return null;
            }
        }

        public static List<Process> GetChildrenById(int id)
        {
            try
            {
                var mos = new ManagementObjectSearcher(
                    $"Select * From Win32_Process Where ParentProcessID={id}");
                return (from ManagementObject mo in mos.Get()
                    select Process.GetProcessById(Convert.ToInt32(mo["ProcessID"]))).ToList();
            }
            catch (Exception)
            {
                return null;
            }
        }

        public static List<Process> GetChildProcesses(this Process process)
        {
            try
            {
                var mos = new ManagementObjectSearcher(
                    $"Select * From Win32_Process Where ParentProcessID={process.Id}");
                return (from ManagementObject mo in mos.Get()
                    select Process.GetProcessById(Convert.ToInt32(mo["ProcessID"]))).ToList();
            }
            catch (Exception)
            {
                return null;
            }
        }

        public static bool IsService(this Process process)
        {
            if (process == null)
            {
                return false;
            }
            using (var searcher =
                new ManagementObjectSearcher("SELECT * FROM Win32_Service WHERE ProcessId =" + "\"" + process.Id +
                                             "\""))
            {
                if (searcher.Get().Cast<ManagementObject>().Any())
                {
                    return true;
                }
            }
            return false;
        }

        [DllImport("kernel32.dll")]
        public static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId);

        [DllImport("psapi.dll")]
        private static extern uint GetModuleFileNameEx(IntPtr hProcess, IntPtr hModule, [Out] StringBuilder lpBaseName,
            [In] [MarshalAs(UnmanagedType.U4)] int nSize);

        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool CloseHandle(IntPtr hObject);


        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static string GetProcessName(this Process proc)
        {
            var processHandle = OpenProcess(0x0400 | 0x0010, false, proc.Id);

            if (processHandle == IntPtr.Zero)
            {
                return null;
            }

            const int lengthSb = 4000;

            var sb = new StringBuilder(lengthSb);

            string result = null;

            if (GetModuleFileNameEx(processHandle, IntPtr.Zero, sb, lengthSb) > 0)
            {
                result = Path.GetFileName(sb.ToString());
            }

            CloseHandle(processHandle);

            return result;
        }

        public static Process GetProcess(string path)
        {
            try
            {
                return Process.GetProcessesByName(Path.GetFileNameWithoutExtension(path)).FirstOrDefault();
            }
            catch
            {

                return null;
            }
        }

        private static Process FindPidFromIndexedProcessName(string indexedProcessName)
        {
            try
            {
                var parentId = new PerformanceCounter("Process", "Creating Process ID", indexedProcessName);
                return Process.GetProcessById((int)parentId.NextValue());
            }
            catch (Exception)
            {
                return null;
            }
        }


        public static void KillProcessAndChildren(this Process process)
        {
            try
            {
                var searcher = new ManagementObjectSearcher("Select * From Win32_Process Where ParentProcessID=" + process.Id);
                var moc = searcher.Get();
                foreach (var o in moc)
                {
                    var mo = (ManagementObject)o;
                    var child = Process.GetProcessById(Convert.ToInt32(mo["ProcessID"]));
                    KillProcessAndChildren(child);
                    child.Kill();
                }
                process.Kill();
            }
            catch
            {
                // Process already exited.
            }
        }

        public static bool ProgramIsRunning(string fullPath)
        {
            return Process.GetProcessesByName(Path.GetFileNameWithoutExtension(fullPath)).Count() > 1;
        }

        public static Process Parent(this Process process)
        {
            return FindPidFromIndexedProcessName(FindIndexedProcessName(process.Id));
        }
    }
}
﻿#region

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Web.UI;
using MassTransit.Util;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

#endregion

namespace UlteriusServer.Utilities.Extensions
{
    /// <summary>
    ///     Enum FormatTokenFlags
    /// </summary>
    public enum FormatTokenFlags
    {
        /// <summary>
        ///     Uses the specifier token as the replacement token, matches '%' but not '%%'
        /// </summary>
        SpecifierToken,

        /// <summary>
        ///     Like String.Format
        /// </summary>
        IndexToken,

        /// <summary>
        ///     Extracts an Object's Members by name.
        /// </summary>
        MemberToken
    }

    /// <summary>
    ///     Class StringExtensions
    /// </summary>
    public static class StringExtensions
    {

        // Returns the human-readable file totalSize for an arbitrary, 64-bit file totalSize 
        // The default format is "0.### XB", e.g. "4.2 KB" or "1.434 GB"

        public static string UnicodeUtf8(this string strFrom)
        {
            var bytSrc = Encoding.Unicode.GetBytes(strFrom);
            var bytDestination = Encoding.Convert(Encoding.Unicode, Encoding.UTF8, bytSrc);
            var strTo = Encoding.UTF8.GetString(bytDestination);
            return strTo;
        }

        /// <summary>
        /// Implement's VB's Like operator logic.
        /// </summary>
        public static bool IsLike(this string s, string pattern)
        {
            // Characters matched so far
            var matched = 0;

            // Loop through pattern string
            for (var i = 0; i < pattern.Length;)
            {
                // Check for end of string
                if (matched > s.Length)
                    return false;

                // Get next pattern character
                var c = pattern[i++];
                if (c == '[') // Character list
                {
                    // Test for exclude character
                    var exclude = (i < pattern.Length && pattern[i] == '!');
                    if (exclude)
                        i++;
                    // Build character list
                    var j = pattern.IndexOf(']', i);
                    if (j < 0)
                        j = s.Length;
                    var charList = CharListToSet(pattern.Substring(i, j - i));
                    i = j + 1;

                    if (charList.Contains(s[matched]) == exclude)
                        return false;
                    matched++;
                }
                else if (c == '?') // Any single character
                {
                    matched++;
                }
                else if (c == '#') // Any single digit
                {
                    if (!Char.IsDigit(s[matched]))
                        return false;
                    matched++;
                }
                else if (c == '*') // Zero or more characters
                {
                    if (i < pattern.Length)
                    {
                        // Matches all characters until
                        // next character in pattern
                        var next = pattern[i];
                        var j = s.IndexOf(next, matched);
                        if (j < 0)
                            return false;
                        matched = j;
                    }
                    else
                    {
                        // Matches all remaining characters
                        matched = s.Length;
                        break;
                    }
                }
                else // Exact character
                {
                    if (matched >= s.Length || c != s[matched])
                        return false;
                    matched++;
                }
            }
            // Return true if all characters matched
            return (matched == s.Length);
        }
        /// <summary>
        /// Checks if a string is a valid email
        /// </summary>
        /// <param name="email"></param>
        /// <returns></returns>
        public static bool IsValidEmail(this string email)
        {
            try
            {
                var addr = new System.Net.Mail.MailAddress(email);
                return addr.Address == email;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// Returns true if <paramref name="path"/> starts with the path <paramref name="baseDirPath"/>.
        /// The comparison is case-insensitive, handles / and \ slashes as folder separators and
        /// only matches if the base dir folder name is matched exactly ("c:\foobar\file.txt" is not a sub path of "c:\foo").
        /// </summary>
        public static bool IsSubPathOf(this string path, string baseDirPath)
        {
            var normalizedPath = Path.GetFullPath(path.Replace('/', '\\')
                .WithEnding("\\"));

            var normalizedBaseDirPath = Path.GetFullPath(baseDirPath.Replace('/', '\\')
                .WithEnding("\\"));

            return normalizedPath.StartsWith(normalizedBaseDirPath, StringComparison.OrdinalIgnoreCase);
        }

        /// <summary>
        /// Returns <paramref name="str"/> with the minimal concatenation of <paramref name="ending"/> (starting from end) that
        /// results in satisfying .EndsWith(ending).
        /// </summary>
        /// <example>"hel".WithEnding("llo") returns "hello", which is the result of "hel" + "lo".</example>
        public static string WithEnding([CanBeNull] this string str, string ending)
        {
            if (str == null)
                return ending;

            var result = str;

            // Right() is 1-indexed, so include these cases
            // * Append no characters
            // * Append up to N characters, where N is ending length
            for (var i = 0; i <= ending.Length; i++)
            {
                var tmp = result + ending.Right(i);
                if (tmp.EndsWith(ending))
                    return tmp;
            }

            return result;
        }

        /// <summary>Gets the rightmost <paramref name="length" /> characters from a string.</summary>
        /// <param name="value">The string to retrieve the substring from.</param>
        /// <param name="length">The number of characters to retrieve.</param>
        /// <returns>The substring.</returns>
        public static string Right([NotNull] this string value, int length)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }
            if (length < 0)
            {
                throw new ArgumentOutOfRangeException("length", length, "Length is less than zero");
            }

            return (length < value.Length) ? value.Substring(value.Length - length) : value;
        }

        /// <summary>
        /// Converts a string of characters to a HashSet of characters. If the string
        /// contains character ranges, such as A-Z, all characters in the range are
        /// also added to the returned set of characters.
        /// </summary>
        /// <param name="charList">Character list string</param>
        private static HashSet<char> CharListToSet(string charList)
        {
            var set = new HashSet<char>();

            for (var i = 0; i < charList.Length; i++)
            {
                if ((i + 1) < charList.Length && charList[i + 1] == '-')
                {
                    // Character range
                    var startChar = charList[i++];
                    i++; // Hyphen
                    var endChar = (char)0;
                    if (i < charList.Length)
                        endChar = charList[i++];
                    for (int j = startChar; j <= endChar; j++)
                        set.Add((char)j);
                }
                else set.Add(charList[i]);
            }
            return set;
        }

        public static string GetBytesReadable(long i)
        {
            // Get absolute value
            var absoluteI = i < 0 ? -i : i;
            // Determine the suffix and readable value
            string suffix;
            double readable;
            if (absoluteI >= 0x1000000000000000) // Exabyte
            {
                suffix = "EB";
                readable = i >> 50;
            }
            else if (absoluteI >= 0x4000000000000) // Petabyte
            {
                suffix = "PB";
                readable = i >> 40;
            }
            else if (absoluteI >= 0x10000000000) // Terabyte
            {
                suffix = "TB";
                readable = i >> 30;
            }
            else if (absoluteI >= 0x40000000) // Gigabyte
            {
                suffix = "GB";
                readable = i >> 20;
            }
            else if (absoluteI >= 0x100000) // Megabyte
            {
                suffix = "MB";
                readable = i >> 10;
            }
            else if (absoluteI >= 0x400) // Kilobyte
            {
                suffix = "KB";
                readable = i;
            }
            else
            {
                return i.ToString("0 B"); // Byte
            }
            // Divide by 1024 to get fractional value
            readable = readable / 1024;
            // Return formatted number with suffix
            return readable.ToString("0.### ") + suffix;
        }

        /// <summary>
        /// Returns a Secure string from the source string
        /// </summary>
        /// <param name="Source"></param>
        /// <returns></returns>
        public static SecureString ToSecureString(this string Source)
        {
            if (string.IsNullOrWhiteSpace(Source))
                return null;
            var Result = new SecureString();
            foreach (var c in Source.ToCharArray())
                Result.AppendChar(c);
            return Result;
        }
        public static string ToUnsecureString(this SecureString secureString)
        {
            if (secureString == null) throw new ArgumentNullException("secureString");

            var unmanagedString = IntPtr.Zero;
            try
            {
                unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(secureString);
                return Marshal.PtrToStringUni(unmanagedString);
            }
            finally
            {
                Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString);
            }
        }


        /// <summary>
        ///     The Reformatting function called to format the string with a list of arguments.
        /// </summary>
        private static Func<Func<string, object>, string, IList<object>, string> _regexReformatter;

        /// <summary>
        ///     The Regex which matches the specifier token in strings.
        /// </summary>
        private static Regex _specifierTokenRegex;

        /// <summary>
        ///     The Regex which matches parameter indexes in strings, same as string.Format.
        /// </summary>
        private static Regex _argumentIndexRegex;

        /// <summary>
        ///     The Regex which matches object member names in strings.
        /// </summary>
        private static Regex _objectMemberRegex;

        /// <summary>
        ///     Splits a string into an array of strings, the string is split by commas.
        /// </summary>
        /// <param name="this">The string instance to split by commas.</param>
        /// <returns>The <paramref name="this" /> string that has been comma separated into substrings.</returns>
        public static string[] CommaSeparate(this string @this)
        {
            return @this.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
        }

        /// <summary>
        ///     Determines whether two String objects contain the same data, ignoring the case of the letters in the String; uses
        ///     Ordinal comparison.
        /// </summary>
        /// <param name="this">The current string to be compared to.</param>
        /// <param name="other">The other string to compare against the current String for equality.</param>
        /// <returns><c>true</c> if the two strings are equal, <c>false</c> otherwise</returns>
        public static bool EqualsIgnoreCase(this string @this, string other)
        {
            return string.Equals(@this, other, StringComparison.OrdinalIgnoreCase);
        }

        public static bool IsBase64String(this string s)
        {
            s = s.Trim();
            return (s.Length%4 == 0) && Regex.IsMatch(s, @"^[a-zA-Z0-9\+/]*={0,3}$", RegexOptions.None);
        }

        public static bool IsValidJson(this string strInput)
        {
            strInput = strInput.Trim();
            if ((strInput.StartsWith("{") && strInput.EndsWith("}")) || //For object
                (strInput.StartsWith("[") && strInput.EndsWith("]"))) //For array
            {
                try
                {
                    JToken.Parse(strInput);
                    return true;
                }
                catch (JsonReaderException)
                {
                    //Exception in parsing json
                    return false;
                }
                catch (Exception) //some other exception
                {
                    return false;
                }
            }
            return false;
        }


        /// <summary>
        ///     Replaces one or more format items in a specified string with the string representation of a specified object.
        /// </summary>
        /// <returns>
        ///     A copy of <paramref name="format" /> in which any format items are replaced by the string representation of
        ///     <paramref name="values" />.
        /// </returns>
        /// <param name="format">A composite format string. </param>
        /// <param name="values">The arguments to use in formatting <paramref name="format" />.</param>
        public static string Form(this string format, params object[] values)
        {
            var specifierTokenMatches = _specifierTokenRegex.Matches(format);
            var indexTokenMatches = _argumentIndexRegex.Matches(format);
            var memberNameMatches = _objectMemberRegex.Matches(format);

            if (memberNameMatches.Count > 0 && values.Length == 1)
            {
                format = FormatString(format, FormatTokenFlags.MemberToken, values);
            }
            else
            {
                if (indexTokenMatches.Count > 0)
                {
                    format = FormatString(format, FormatTokenFlags.IndexToken, values);
                }

                if (specifierTokenMatches.Count > 0)
                {
                    format = FormatString(format, FormatTokenFlags.SpecifierToken, values);
                }
            }
            return format;
        }

        public static string CreateMD5(this string input)
        {
            // Use input string to calculate MD5 hash
            using (var md5 = MD5.Create())
            {
                var inputBytes = Encoding.ASCII.GetBytes(input);
                var hashBytes = md5.ComputeHash(inputBytes);

                // Convert the byte array to hexadecimal string
                var sb = new StringBuilder();
                foreach (var t in hashBytes)
                {
                    sb.Append(t.ToString("X2"));
                }
                return sb.ToString();
            }
        }

        /// <summary>
        ///     The Function which does all the heavy lifting.
        /// </summary>
        /// <param name="format">A composite format string</param>
        /// <param name="flags">The flags which specify how the <paramref name="format" /> string should be interpreted.</param>
        /// <param name="arguments">The arguments to format the <paramref name="format" /> parameter with.</param>
        /// <returns>System.String.</returns>
        public static string FormatString(string format, FormatTokenFlags flags, params object[] arguments)
        {
            switch (flags)
            {
                case FormatTokenFlags.IndexToken:
                    return string.Format(format, arguments);

                case FormatTokenFlags.SpecifierToken:
                    var stringBuilder = new StringBuilder();
                    for (int i = 0,
                        argIndex = 0;
                        i < format.Length;
                        i++)
                    {
                        stringBuilder.Append(format[i] == '%' && argIndex < arguments.Length
                            ? "{" + argIndex++ + "}"
                            : format.Substring(i, 1));
                    }
                    return string.Format(stringBuilder.ToString(), arguments);

                case FormatTokenFlags.MemberToken:
                    return
                        string.Format(
                            _regexReformatter(name => name == "0" ? arguments[0] : DataBinder.Eval(arguments[0], name),
                                format, arguments), arguments);

                default:
                    return format;
            }
        }

        public static void Initialize()
        {
            const RegexOptions regexOptions = RegexOptions.Compiled | RegexOptions.CultureInvariant;
            _objectMemberRegex = new Regex(@"(?<start>(\{))+(?<property>[\w\.]+)(?<end>(\}))+", regexOptions);
            _specifierTokenRegex = new Regex(@"(?<!\\)%", regexOptions);
            _argumentIndexRegex = new Regex(@"\{(\d)\}", regexOptions);
            _regexReformatter = (valueFetcher, format, parameters) =>
            {
                var argumentCollection = new List<object>();
                var rewrittenFormat = _objectMemberRegex.Replace(format, match =>
                {
                    Group startGroup = match.Groups["start"],
                        propertyGroup = match.Groups["property"],
                        endGroup = match.Groups["end"];

                    var result = valueFetcher(propertyGroup.Value);

                    argumentCollection.Add(result);
                    var index = argumentCollection.Count - 1;
                    var fmt = new string('{', startGroup.Captures.Count) + index +
                              new string('}', endGroup.Captures.Count);
                    return string.Format(fmt, argumentCollection.ToArray());
                });

                return rewrittenFormat;
            };
        }
    }
using UlteriusServer.Api.Win32;
using UlteriusServer.Utilities.Extensions;
      
                if (username.IsValidEmail())
                {
                    domainName = "MicrosoftAccount";
                }
using UlteriusServer.Api.Win32;
using UlteriusServer.Api.Win32.ScreenShare;
using UlteriusServer.Utilities.Extensions;
               
                managerProcess = Process.Start(managerPath);
               //
            var agentPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),"UlteriusAgent.exe");
            agentProcess = Process.Start(agentPath);
            ScreenData.SetupDuplication();
                    Process.Start("CMD.exe", command);
                        $"firewall add allowedprogram program=\"{exeFileName}\" name=\"{displayName}\" profile=\"ALL\"",
            proc?.WaitForExit();
            var me = Process.GetCurrentProcess();
            var parent = me.Parent();
            return parent != null && parent.IsService();
using UlteriusServer.Utilities;
using UlteriusServer.Utilities;
using UlteriusServer.Utilities.Extensions;
               
                    var targetPath = Path.GetDirectoryName(new DirectoryInfo(filename).FullName);
                    //prevent directory traversal, we should only allow access to the root directory of the HTTP Server.
                    if (!targetPath.IsSubPathOf(_rootDirectory))
                    {
                        context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
                        return;
                    }
        private WebSocketListener _listener;
        public WebSocketEventListener(Uri[] endpoints)
        public WebSocketEventListener(Uri[] endpoints, WebSocketListenerOptions options)
            options.Standards.RegisterRfc6455();
            _listener = new WebSocketListener(endpoints, options);
            _listener?.StopAsync().GetAwaiter().GetResult();
        public async void Start()
            await _listener.StartAsync();
        public async void Stop()
            await _listener.StopAsync();
            Task.Run(() => HandleListners(_listener));
﻿<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="AForge" version="2.2.5" targetFramework="net461" />
  <package id="AForge.Imaging" version="2.2.5" targetFramework="net461" />
  <package id="AForge.Math" version="2.2.5" targetFramework="net461" />
  <package id="AForge.Video" version="2.2.5" targetFramework="net461" />
  <package id="AForge.Video.DirectShow" version="2.2.5" targetFramework="net461" />
  <package id="AForge.Vision" version="2.2.5" targetFramework="net461" />
  <package id="BouncyCastle" version="1.8.1" targetFramework="net461" />
  <package id="deniszykov.WebSocketListener" version="4.0.0" targetFramework="net461" />
  <package id="DotNetZip" version="1.10.1" targetFramework="net461" />
  <package id="JonSkeet.MiscUtil" version="0.2.0" targetFramework="net461" />
  <package id="log4net" version="2.0.8" targetFramework="net461" />
  <package id="Magnum" version="2.1.3" targetFramework="net461" />
  <package id="MassTransit" version="2.9.0" targetFramework="net461" />
  <package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="1.0.3" targetFramework="net461" />
  <package id="Microsoft.Net.Compilers" version="2.4.0" targetFramework="net461" developmentDependency="true" />
  <package id="Microsoft.Tpl.Dataflow" version="4.5.24" targetFramework="net461" />
  <package id="Mono.Cecil" version="0.9.6.4" targetFramework="net461" />
  <package id="Newtonsoft.Json" version="10.0.3" targetFramework="net461" />
  <package id="Open.NAT" version="2.1.0.0" targetFramework="net461" />
  <package id="SharpDX" version="4.0.1" targetFramework="net461" />
  <package id="SharpDX.Direct3D11" version="4.0.1" targetFramework="net461" />
  <package id="SharpDX.DXGI" version="4.0.1" targetFramework="net461" />
  <package id="SharpDX.Mathematics" version="4.0.1" targetFramework="net461" />
  <package id="System.Threading.Tasks.Dataflow" version="4.8.0" targetFramework="net461" />
  <package id="Topshelf" version="4.0.3" targetFramework="net461" />
  <package id="TurboJpegWrapper" version="1.4.2.6" targetFramework="net461" />
  <package id="ZetaLongPaths" version="1.0.0.19" targetFramework="net461" />
<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1"/>
    </startup>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
        <bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0"/>
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Magnum" publicKeyToken="b800c4cfcdeea87b" culture="neutral"/>
        <bindingRedirect oldVersion="0.0.0.0-2.1.3.0" newVersion="2.1.3.0"/>
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="AsyncIO" publicKeyToken="44a94435bd6f33f8" culture="neutral"/>
        <bindingRedirect oldVersion="0.0.0.0-0.1.25.0" newVersion="0.1.25.0"/>
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>
using Topshelf;
using Warden.Core;
            WardenManager.Initialize(new WardenOptions
                DeepKill = true,
                CleanOnExit = true,
                ReadFileHeaders = false
            });
            HostFactory.Run(x => //1
                x.Service<UlteriusAgent>(s => //2
                    s.ConstructUsing(name => new UlteriusAgent()); //3
                    s.WhenStarted(tc => tc.Start()); //4
                    s.WhenStopped(tc => tc.Stop());
                    s.WhenSessionChanged((se, e, id) => { se.HandleEvent(e, id); }); //5
                });
                x.OnException(ex =>
                    //TODO Logging
                });
                x.RunAsLocalSystem(); //6
                x.EnableSessionChanged();
                x.EnableServiceRecovery(r => { r.RestartService(1); });
                x.SetDescription("The server that powers Ulterius"); //7
                x.SetDisplayName("Ulterius Server"); //8
                x.SetServiceName("UlteriusServer"); //9
                x.StartAutomaticallyDelayed();
            });
﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Topshelf;
using Warden.Core;
using Warden.Core.Utils;

namespace UlteriusAgent
{
    public class UlteriusAgent
    {
        private readonly string _ulteriusPath;
        private WardenProcess _ulteriusInstance;


        public UlteriusAgent()
        {
            const string ulteriusFileName = "Ulterius Server.exe";
            _ulteriusPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ulteriusFileName);
        }

        public void Start()
        {
            if (!File.Exists(_ulteriusPath))
            {
                throw new InvalidOperationException($"Unable to locate Ulterius at {_ulteriusPath}");
            }
            if (Respawn())
            {
                Console.WriteLine("Rainway started as a service!");
                Console.ReadLine();
            }
            else
            {
                Console.WriteLine("Failed to start Rainway!");
                Environment.Exit(1);
            }
        }

        private bool Respawn()
        {
            _ulteriusInstance = null;
            _ulteriusInstance = WardenProcess.Start(_ulteriusPath, string.Empty, null, true).GetAwaiter().GetResult();
            if (_ulteriusInstance == null || !_ulteriusInstance.IsTreeActive())
            {
                return false;
            }
            _ulteriusInstance.OnStateChange += UlteriusInstanceOnOnStateChange;
            return true;
        }

        public void Stop()
        {
            const string ulteriusFileName = "Ulterius Server.exe";
            if (_ulteriusInstance != null)
            {
                _ulteriusInstance?.Kill();
                WardenManager.Flush(_ulteriusInstance.Id);
            }
            _ulteriusInstance = null;
            EndProcessTree(ulteriusFileName);
        }

        private void EndProcessTree(string imageName)
        {
            try
            {
                var taskKill = new TaskKill
                {
                    Arguments = new List<TaskSwitch>()
                    {
                        TaskSwitch.Force,
                        TaskSwitch.TerminateChildren,
                        TaskSwitch.ImageName.SetValue(imageName)
                    }
                };
                taskKill.Execute(out var output, out var errror);
            }
            catch
            {
                //
            }
        }

        private void UlteriusInstanceOnOnStateChange(object sender, StateEventArgs stateEventArgs)
        {
            if (stateEventArgs.Id == _ulteriusInstance.Id && stateEventArgs.State == ProcessState.Dead)
            {
                //Kill the entire tree.
                _ulteriusInstance.Kill();
                WardenManager.Flush(_ulteriusInstance.Id);
                if (Respawn())
                {
                   Console.WriteLine("Rainway restarted!");
                }
            }
        }

        public void HandleEvent(HostControl hostControl, SessionChangedArguments arg3)
        {
            
        }
    }
}
﻿<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{686AE4C4-791F-45EB-9414-029D6115905D}</ProjectGuid>
    <OutputType>Exe</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>UlteriusAgent</RootNamespace>
    <AssemblyName>UlteriusAgent</AssemblyName>
    <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
    <NuGetPackageImportStamp>
    </NuGetPackageImportStamp>
    <TargetFrameworkProfile />
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <LangVersion>7</LangVersion>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <Prefer32Bit>false</Prefer32Bit>
    <LangVersion>7</LangVersion>
  </PropertyGroup>
  <PropertyGroup>
    <StartupObject />
  </PropertyGroup>
  <PropertyGroup>
    <ApplicationManifest>app.manifest</ApplicationManifest>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="Topshelf, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b800c4cfcdeea87b, processorArchitecture=MSIL">
      <HintPath>..\packages\Topshelf.4.0.3\lib\net452\Topshelf.dll</HintPath>
    </Reference>
    <Reference Include="Warden, Version=1.2.3.0, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\packages\Warden.NET.1.2.3\lib\net45\Warden.dll</HintPath>
      <Private>True</Private>
    </Reference>
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Program.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
    <Compile Include="UlteriusAgent.cs" />
  </ItemGroup>
  <ItemGroup>
    <None Include="App.config">
      <SubType>Designer</SubType>
    </None>
    <None Include="app.manifest" />
    <None Include="packages.config" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
﻿<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Topshelf" version="4.0.3" targetFramework="net452" />
  <package id="Warden.NET" version="1.2.3" targetFramework="net452" />
</packages>
﻿
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27004.2005
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UlteriusServer", "RemoteTaskServer\UlteriusServer.csproj", "{E9A365D5-AEBE-4AF3-86C5-D17BC65ADE46}"
	ProjectSection(ProjectDependencies) = postProject
		{3549CD6F-80F8-450F-B99E-CF0A736B1F2A} = {3549CD6F-80F8-450F-B99E-CF0A736B1F2A}
		{686AE4C4-791F-45EB-9414-029D6115905D} = {686AE4C4-791F-45EB-9414-029D6115905D}
	EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UlteriusAgent", "UlteriusAgent\UlteriusAgent.csproj", "{686AE4C4-791F-45EB-9414-029D6115905D}"
	ProjectSection(ProjectDependencies) = postProject
		{3549CD6F-80F8-450F-B99E-CF0A736B1F2A} = {3549CD6F-80F8-450F-B99E-CF0A736B1F2A}
	EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsInput", "..\..\..\inputsimulator2\WindowsInput\WindowsInput.csproj", "{3549CD6F-80F8-450F-B99E-CF0A736B1F2A}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|Any CPU = Debug|Any CPU
		Release|Any CPU = Release|Any CPU
	EndGlobalSection
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
		{E9A365D5-AEBE-4AF3-86C5-D17BC65ADE46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{E9A365D5-AEBE-4AF3-86C5-D17BC65ADE46}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{E9A365D5-AEBE-4AF3-86C5-D17BC65ADE46}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{E9A365D5-AEBE-4AF3-86C5-D17BC65ADE46}.Release|Any CPU.Build.0 = Release|Any CPU
		{686AE4C4-791F-45EB-9414-029D6115905D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{686AE4C4-791F-45EB-9414-029D6115905D}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{686AE4C4-791F-45EB-9414-029D6115905D}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{686AE4C4-791F-45EB-9414-029D6115905D}.Release|Any CPU.Build.0 = Release|Any CPU
		{3549CD6F-80F8-450F-B99E-CF0A736B1F2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{3549CD6F-80F8-450F-B99E-CF0A736B1F2A}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{3549CD6F-80F8-450F-B99E-CF0A736B1F2A}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{3549CD6F-80F8-450F-B99E-CF0A736B1F2A}.Release|Any CPU.Build.0 = Release|Any CPU
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
	GlobalSection(ExtensibilityGlobals) = postSolution
		SolutionGuid = {9CC02739-8FB9-4530-9C74-0436AF2D60A7}
	EndGlobalSection
EndGlobal