diff --git a/.gitignore b/.gitignore index dd701dc..a736671 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ TestResults [Dd]ebug/ [Rr]elease/ x64/ +.vs/ *_i.c *_p.c *.ilk 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 @@ - - - - - Debug - AnyCPU - {5C3B0B17-CBB7-4B4B-B527-1FAB2BB96466} - Library - Properties - AgentInterface - AgentInterface - v4.5.2 - 512 - - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - true - - - true - - - - ..\packages\Cassia.2.0.0.60\lib\2.0\Cassia.dll - True - - - ..\packages\Newtonsoft.Json.10.0.1-beta1\lib\net45\Newtonsoft.Json.dll - - - ..\packages\OpenHardwareMonitor.0.7.1\lib\net40\OpenHardwareMonitorLib.dll - True - - - - - ..\packages\SharpDX.3.1.1\lib\net45\SharpDX.dll - True - - - ..\packages\SharpDX.Direct3D11.3.1.1\lib\net45\SharpDX.Direct3D11.dll - True - - - ..\packages\SharpDX.DXGI.3.1.1\lib\net45\SharpDX.DXGI.dll - True - - - ..\packages\SharpDX.Mathematics.3.1.1\lib\net45\SharpDX.Mathematics.dll - True - - - - - - - - - ..\packages\TurboJpegWrapper.1.4.2.6\lib\net35\TurboJpegWrapper.dll - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Designer - - - - - - - - - - - - - - - - (); -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); -]]> - - - - - - - - - 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}. - - - - - \ 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 - { - /// The device is part of the desktop. - AttachedToDesktop = 0x1, - MultiDriver = 0x2, - - /// The device is part of the desktop. - PrimaryDevice = 0x4, - - /// Represents a pseudo device used to mirror application drawing for remoting or other purposes. - MirroringDriver = 0x8, - - /// The device is VGA compatible. - VgaCompatible = 0x10, - - /// The device is removable; it cannot be the primary display. - Removable = 0x20, - - /// The device has more display modes than its output devices support. - 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 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 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 UpdateDisplays() - { - var monitors = new List(); - 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>(); - 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()); - 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() - { - 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 -{ - /// - /// Class that allows running applications with full admin rights. In - /// addition the application launched will bypass the Vista UAC prompt. - /// - 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; - } - } - - - /// - /// Launches the given application with full admin rights, and in addition bypasses the Vista UAC prompt - /// - /// The name of the application to launch - /// Process information regarding the launched application that gets returned to the caller - /// - 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 @@ - - - - \ 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 keyCodes); - - [OperationContract(IsOneWay = true)] - void HandleKeyUp(List keyCodes); - - [OperationContract(IsOneWay = true)] - void HandleRightClick(); - - [OperationContract] - float GetGpuTemp(string gpuName); - - [OperationContract] - List GetDisplayInformation(); - - [OperationContract] - List 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 @@ - - - - - - - - - - - \ 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 @@ -7,6 +7,7 @@ using UlteriusServer.Utilities.Security; using UlteriusServer.WebSocketAPI.Authentication; using vtortola.WebSockets; +using vtortola.WebSockets.Http; using static UlteriusServer.Utilities.Security.UlteriusAes; #endregion @@ -41,6 +42,7 @@ 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 @@ -55,8 +57,11 @@ public void WriteMessage(object data) { if (_authClient != null) { + if (_authClient.AesShook) { + + var keyBytes = Encoding.UTF8.GetBytes(Rsa.SecureStringToString(_authClient.AesKey)); var keyIv = Encoding.UTF8.GetBytes(Rsa.SecureStringToString(_authClient.AesIv)); @@ -71,7 +76,7 @@ public void WriteMessage(object data) 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; @@ -88,7 +93,7 @@ public void WriteMessage(object data) 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); } } @@ -104,6 +109,7 @@ 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)); @@ -121,7 +127,7 @@ public void WriteScreenFrame(byte[] data) 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); } } 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,7 +1,7 @@ #region using System.Collections.Generic; -using AgentInterface.Api.Models; +using UlteriusServer.Api.Win32.ScreenShare.Models; #endregion 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 @@ -6,7 +6,6 @@ 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; 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,7 +1,7 @@ #region -using AgentInterface.Api.Win32; using UlteriusServer.Api.Network.Messages; +using UlteriusServer.Api.Win32; using UlteriusServer.WebSocketAPI.Authentication; using vtortola.WebSockets; @@ -43,18 +43,18 @@ public override void HandlePacket(Packet packet) 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(); @@ -63,13 +63,13 @@ private void RotateDisplay() { 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()); @@ -79,7 +79,7 @@ private void ChangeScreenResolution() { 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 @@ -6,9 +6,9 @@ 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; 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 @@ -3,7 +3,6 @@ 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; @@ -54,9 +53,7 @@ public void GetGpuInformation() private float? GetGpuTemp(string gpuName) { - return UlteriusApiServer.RunningAsService - ? UlteriusApiServer.AgentClient.GetGpuTemp(gpuName) - : SystemData.GetGpuTemp(gpuName); + return SystemData.GetGpuTemp(gpuName); } 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 @@ -7,9 +7,9 @@ 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; @@ -33,29 +33,10 @@ public void StartProcess() 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) { 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 @@ -10,10 +10,10 @@ 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; @@ -125,9 +125,7 @@ public void StartScreenShare() 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 { @@ -148,41 +146,6 @@ public void StartScreenShare() } } - - 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) @@ -208,6 +171,10 @@ 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(); @@ -243,6 +210,10 @@ private void SendPolledFrame(Bitmap screenImage, Rectangle bounds) public override void HandlePacket(Packet packet) { + if (RunningAsService && DesktopWatcher.CurrentDesktop != null) + { + Desktop.SetCurrent(DesktopWatcher.CurrentDesktop); + } _client = packet.Client; _authClient = packet.AuthClient; _packet = packet; @@ -276,14 +247,7 @@ public override void HandlePacket(Packet packet) HandleKeyUp(); break; case PacketManager.EndPoints.FullFrame: - if (RunningAsService) - { - HandleAgentFullFrame(); - } - else - { - HandleFullFrame(); - } + HandleFullFrame(); break; case PacketManager.EndPoints.RightClick: HandleRightClick(); @@ -316,68 +280,12 @@ private void HandleCtrlAltDel() 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() @@ -427,7 +335,6 @@ private void HandleFullFrame() private void HandleKeyUp() { - if (!ScreenShareService.Streams.ContainsKey(_authClient)) return; var keyCodes = ((IEnumerable)_packet.Args[0]).Cast() .Select(x => x.ToString()) .ToList(); @@ -436,17 +343,10 @@ private void HandleKeyUp() .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); } } @@ -458,7 +358,6 @@ private string ToHex(int value) private void HandleKeyDown() { - if (!ScreenShareService.Streams.ContainsKey(_authClient)) return; var keyCodes = ((IEnumerable)_packet.Args[0]).Cast() .Select(x => x.ToString()) .ToList(); @@ -466,35 +365,20 @@ private void HandleKeyDown() 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) @@ -510,77 +394,36 @@ private static Point GetRelativeCoordinates(Point absoluteCoordinates) 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 @@ -8,8 +8,8 @@ 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; 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 @@ -3,9 +3,9 @@ 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; 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.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.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 keyCodes) - { - try - { - InputChannel.HandleKeyDown(keyCodes); - } - catch (EndpointNotFoundException) - { - } - catch (CommunicationException) - { - } - } - - public void HandleKeyUp(List 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 GetDisplayInformation() - { - try - { - return InputChannel.GetDisplayInformation(); - } - catch (EndpointNotFoundException) - { - return null; - } - catch (CommunicationException) - { - return null; - } - } - - public List 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 @@ -13,12 +13,13 @@ 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 @@ -199,18 +200,31 @@ private async void Updater() private List GetDisplayInformation() { - var displayList = DisplayInformation(); - if (!UlteriusApiServer.RunningAsService) return displayList; - var displayInfo = UlteriusApiServer.AgentClient.GetDisplayInformation(); - return displayInfo ?? displayList; + var displays = new List(); + 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 GetCpuTemps() { - return UlteriusApiServer.RunningAsService - ? UlteriusApiServer.AgentClient.GetCpuTemps() - : SystemData.GetCpuTemps(); + return SystemData.GetCpuTemps(); } @@ -231,7 +245,7 @@ public string GetMotherBoard() _motherBoard = "Board Unknown"; } } - return _motherBoard; + return string.IsNullOrEmpty(_motherBoard) ? "Board Unknown" : _motherBoard; } @@ -242,14 +256,14 @@ private static object GetNetworkInfo() 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 @@ -7,7 +7,7 @@ using System.Net.NetworkInformation; using System.Net.Sockets; using System.Runtime.InteropServices; -using AgentInterface.Settings; +using UlteriusServer.Utilities; #endregion 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,12 +1,13 @@ #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 @@ -52,10 +53,8 @@ private async void Updater() 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); } 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 GetCpuTemps() - { - var myComputer = new Computer(); - myComputer.Open(); - myComputer.CPUEnabled = true; - var tempTemps = new List(); - 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 GetCpuTemps() + { + var myComputer = new Computer(); + myComputer.Open(); + myComputer.CPUEnabled = true; + var tempTemps = new List(); + 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 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; } - - /// - /// Start the API Server - /// - 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(); - ScreenShareService = new ScreenShareService(); - var address = NetworkService.GetAddress(); - var webCamPort = config.Webcams.WebcamPort; - var screenSharePort = config.ScreenShareService.ScreenSharePort; - var endPoints = new List - { - 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(); - } - } - - - - - /// - /// Handles encrypted binary messages - /// - /// - /// - 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); - } - - /// - /// Handles plaintext JSON packets. - /// - /// - /// - 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(); - } - } - - - /// - /// Remove a client when it disconnects - /// - /// - 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!"); - } - } - - /// - /// When a client connects, assign them a unique RSA keypair for handshake. - /// - /// - 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() - }; - client.MessageQueueManagers.TryAdd(clientSocket.LocalEndpoint.Port, new MessageQueueManager()); - AllClients.AddOrUpdate(connectionId, client, (key, value) => value); - await SendWelcomeMessage(client, clientSocket); - } - - /// - /// Sends a new user their unique RSA keypair - /// - /// - /// - 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 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; + + /// + /// Start the API Server + /// + 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(); + 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); + } + + + + + /// + /// Handles encrypted binary messages + /// + /// + /// + 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); + } + + /// + /// Handles plaintext JSON packets. + /// + /// + /// + 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(); + } + } + + + /// + /// Remove a client when it disconnects + /// + /// + 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!"); + } + } + + /// + /// When a client connects, assign them a unique RSA keypair for handshake. + /// + /// + 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() + }; + + client.MessageQueueManagers.TryAdd(host.Port, new MessageQueueManager()); + AllClients.AddOrUpdate(connectionId, client, (key, value) => value); + await SendWelcomeMessage(client, clientSocket); + } + + /// + /// Sends a new user their unique RSA keypair + /// + /// + /// + 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 @@ -9,7 +9,7 @@ #endregion -namespace AgentInterface.Api.Win32 +namespace UlteriusServer.Api.Win32 { /// /// Encapsulates the Desktop API. @@ -61,7 +61,7 @@ public override string ToString() [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. // 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 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 GetMonitors() + { + List monitors = new List(); + + 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,6 +1,6 @@ using System; -namespace AgentInterface.Api.ScreenShare.DesktopDuplication +namespace UlteriusServer.Api.Win32.ScreenShare.DesktopDuplication { public class DesktopDuplicationException : Exception { 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 -{ - /// - /// Provides access to frame-by-frame updates of a particular desktop (i.e. one monitor), with image and cursor - /// information. - /// - 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; - - - /// - /// Duplicates the output of the specified monitor on the specified graphics adapter. - /// - /// The adapter which contains the desired outputs. - /// - /// The output device to duplicate (i.e. monitor). Begins with zero, which seems to - /// correspond to the primary monitor. - /// - 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(); - _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; - } - } - - /// - /// Finds the most capable graphics card. - /// - /// - 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; - } - } - - /// - /// Retrieves the latest desktop image and associated metadata. - /// - 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()) - { - _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 +{ + /// + /// Provides access to frame-by-frame updates of a particular desktop (i.e. one monitor), with image and cursor + /// information. + /// + 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; + + /// + /// Duplicates the output of the specified monitor. + /// + /// The output device to duplicate (i.e. monitor). Begins with zero, which seems to correspond to the primary monitor. + public DesktopDuplicator(int whichMonitor) + : this(0, whichMonitor) { } + + /// + /// Duplicates the output of the specified monitor on the specified graphics adapter. + /// + /// The adapter which contains the desired outputs. + /// + /// The output device to duplicate (i.e. monitor). Begins with zero, which seems to + /// correspond to the primary monitor. + /// + 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(); + _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; + } + } + + /// + /// Finds the most capable graphics card. + /// + /// + 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; + } + } + + /// + /// Retrieves the latest desktop image and associated metadata. + /// + 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()) + { + _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,24 +1,21 @@ #region using System.Drawing; -using System.Runtime.Serialization; #endregion -namespace AgentInterface.Api.ScreenShare.DesktopDuplication +namespace UlteriusServer.Api.Win32.ScreenShare.DesktopDuplication { /// /// Provides image data, cursor data, and image metadata about the retrieved desktop frame. /// - [DataContract] public class DesktopFrame { /// /// Gets the bitmap representing the last retrieved desktop frame. This image spans the entire bounds of the specified /// monitor. /// - [DataMember] public Bitmap DesktopImage { get; set; } @@ -30,7 +27,6 @@ public class DesktopFrame /// To produce a visually accurate copy of the desktop, an application must first process all moved regions before it /// processes updated regions. /// - [DataMember] public MovedRegion[] MovedRegions { get; set; } @@ -40,7 +36,6 @@ public class DesktopFrame /// /// To produce a visually accurate copy of the desktop, an application must first process all moved regions before it processes updated regions. /// - [DataMember] public Rectangle[] UpdatedRegions { get; set; } @@ -48,36 +43,30 @@ public class DesktopFrame /// The number of frames that the operating system accumulated in the desktop image surface since the last retrieved /// frame. /// - [DataMember] public int AccumulatedFrames { get; set; } /// /// 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. /// - [DataMember] public Point CursorLocation { get; set; } /// /// Gets whether the cursor on the last retrieved desktop image was visible. /// - [DataMember] public bool CursorVisible { get; set; } /// /// Gets whether the desktop image contains protected content that was already blacked out in the desktop image. /// - [DataMember] public bool ProtectedContentMaskedOut { get; set; } /// /// Gets whether the operating system accumulated updates by coalescing updated regions. If so, the updated regions /// might contain unmodified pixels. /// - [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,19 +1,14 @@ -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; } /// /// Gets the target region to where the operating system moved the image region. /// - [DataMember] public Rectangle Destination { get; internal set; } public void 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,6 +1,6 @@ using System.Drawing; -namespace AgentInterface.Api.ScreenShare.DesktopDuplication +namespace UlteriusServer.Api.Win32.ScreenShare.DesktopDuplication { /// /// Describes the movement of an image rectangle within a desktop frame. 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,6 +1,6 @@ using System.Collections.Generic; -namespace AgentInterface.Api.Models +namespace UlteriusServer.Api.Win32.ScreenShare.Models { public class DisplayInformation { diff --git a/AgentInterface/Api/Models/FrameInformation.cs b/RemoteTaskServer/Api/Win32/ScreenShare/Models/FrameInformation.cs similarity index 56% 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,4 +1,4 @@ -namespace AgentInterface.Api.Models +namespace UlteriusServer.Api.Win32.ScreenShare.Models { public class ResolutionInformation { 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 @@ -4,15 +4,14 @@ 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 { @@ -257,7 +256,7 @@ private static DesktopFrame GetScreenPicDxgi() } catch (Exception) { - _desktopDuplicator = new DesktopDuplicator(); + _desktopDuplicator = new DesktopDuplicator(0); } return frame; } @@ -375,7 +374,7 @@ public static void SetupDuplication() } try { - _desktopDuplicator = new DesktopDuplicator(); + _desktopDuplicator = new DesktopDuplicator(0); _nullFrame = true; CanUseGpuAcceleration = true; Console.WriteLine("desktop duplication setup"); @@ -383,6 +382,7 @@ public static void SetupDuplication() catch (Exception ex) { CanUseGpuAcceleration = false; + Console.WriteLine("desktop duplication failed"); Console.WriteLine(ex.Message); } } 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 @@ -5,7 +5,7 @@ #endregion -namespace AgentInterface.Api.Win32 +namespace UlteriusServer.Api.Win32 { public static class SessionInfo { 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 @@ -9,7 +9,7 @@ #endregion -namespace AgentInterface.Api.Win32 +namespace UlteriusServer.Api.Win32 { [SuppressUnmanagedCodeSecurity] [HostProtection(SecurityAction.LinkDemand, SharedState = true)] 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 @@ -9,7 +9,7 @@ #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 @@ -6,7 +6,7 @@ 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 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 @@ - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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 @@ - - - - - WindowsInput - AgentInterface - Newtonsoft.Json - - - \ 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 @@ -7,7 +7,6 @@ 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; diff --git a/RemoteTaskServer/Program.cs b/RemoteTaskServer/Program.cs index 5115023..308abae 100644 --- a/RemoteTaskServer/Program.cs +++ b/RemoteTaskServer/Program.cs @@ -7,12 +7,7 @@ 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 @@ -38,50 +33,31 @@ private static void Main(string[] args) 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(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(); } } 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 @@ -39,5 +39,5 @@ // 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,10 +1,10 @@ #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 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 @@ -10,6 +10,7 @@ using UlteriusServer.TerminalServer.Messaging.Serialization; using UlteriusServer.TerminalServer.Session; using vtortola.WebSockets; +using ILogger = UlteriusServer.TerminalServer.Infrastructure.ILogger; #endregion @@ -73,7 +74,7 @@ public async Task HandleConnectionAsync(CancellationToken cancellation) { continue; } - Console.WriteLine(queueRequest); + queueRequest.ConnectionId = connectionId; _queue.Publish(queueRequest, type); @@ -84,7 +85,7 @@ public async Task HandleConnectionAsync(CancellationToken cancellation) _log.Error("Error Handling connection", aex.GetBaseException()); try { - _ws.Close(); + _ws.CloseAsync(); } catch { 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 @@ -11,6 +11,7 @@ using UlteriusServer.TerminalServer.Session; using vtortola.WebSockets; using vtortola.WebSockets.Rfc6455; +using ILogger = UlteriusServer.TerminalServer.Infrastructure.ILogger; #endregion @@ -38,14 +39,13 @@ public WebSocketQueueServer(IPEndPoint endpoint, ISystemInfo sysinfo, ILogger lo 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() @@ -58,13 +58,13 @@ public void Dispose() 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 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)) @@ -97,8 +97,10 @@ private void HttpNegotiation(WebSocketHttpRequest request, WebSocketHttpResponse res => { response.Cookies.Add(new Cookie(ConnectionManager.UserSessionCookieName, res.UserId.ToString())); + }); }); + return true; } private async Task AcceptWebSocketClientsAsync(WebSocketListener server) @@ -120,10 +122,11 @@ private async Task AcceptWebSocketClientsAsync(WebSocketListener server) } 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 @@ -4,9 +4,9 @@ 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; @@ -25,24 +25,6 @@ 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(); } @@ -53,18 +35,11 @@ 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; @@ -83,7 +58,11 @@ private void Setup() 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) 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 @@ - - - - - - - Debug - AnyCPU - {E9A365D5-AEBE-4AF3-86C5-D17BC65ADE46} - Exe - Properties - UlteriusServer - Ulterius Server - v4.6.1 - 512 - - - - false - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - true - false - true - - - AnyCPU - true - full - true - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - 6 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - 6 - false - true - - - - - - app.manifest - - - 256.ico - - - - - - false - - - - - - - false - - - - - - - - - - - - - - - - - - - - - Form - - - AboutBox.cs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - True - True - Resources.resx - - - - - - - - - - - - - - - - - - AboutBox.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - - - False - .NET Framework 3.5 SP1 - false - - - - - - - - Designer - - - - - - - - - - - - - ..\packages\AForge.2.2.5\lib\AForge.dll - True - - - ..\packages\AForge.Imaging.2.2.5\lib\AForge.Imaging.dll - True - - - ..\packages\AForge.Math.2.2.5\lib\AForge.Math.dll - True - - - ..\packages\AForge.Video.2.2.5\lib\AForge.Video.dll - True - - - ..\packages\AForge.Video.DirectShow.2.2.5\lib\AForge.Video.DirectShow.dll - True - - - ..\packages\AForge.Vision.2.2.5\lib\AForge.Vision.dll - True - - - ..\packages\BouncyCastle.1.8.1\lib\BouncyCastle.Crypto.dll - True - - - ..\packages\DotNetZip.1.10.1\lib\net20\DotNetZip.dll - True - - - ..\packages\log4net.2.0.7\lib\net45-full\log4net.dll - True - - - ..\packages\Magnum.2.1.3\lib\NET40\Magnum.dll - True - - - ..\packages\MassTransit.2.9.0\lib\net40\MassTransit.dll - True - - - ..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.3\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll - True - - - ..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.dll - True - - - ..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Mdb.dll - True - - - ..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Pdb.dll - True - - - ..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Rocks.dll - True - - - ..\packages\Newtonsoft.Json.10.0.1-beta1\lib\net45\Newtonsoft.Json.dll - - - ..\packages\Open.NAT.2.1.0.0\lib\net45\Open.Nat.dll - True - - - - - - - - - - - False - C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\3.0\System.Management.Automation.dll - - - - - - - ..\packages\System.Threading.Tasks.Dataflow.4.7.0\lib\portable-net45+win8+wpa81\System.Threading.Tasks.Dataflow.dll - True - - - - - - - - ..\packages\Topshelf.4.0.3\lib\net452\Topshelf.dll - True - - - ..\packages\vtortola.WebSocketListener.2.2.2.0\lib\net45\vtortola.WebSockets.dll - True - - - ..\packages\vtortola.WebSocketListener.2.2.2.0\lib\net45\vtortola.WebSockets.Deflate.dll - True - - - ..\packages\vtortola.WebSocketListener.2.2.2.0\lib\net45\vtortola.WebSockets.Rfc6455.dll - True - - - - ..\packages\ZetaLongPaths.1.0.0.14\lib\net40-full\ZetaLongPaths.dll - True - - - - - {58FBCF7C-E7A9-467C-80B3-FC65E8FCCA08} - 1 - 0 - 0 - tlbimp - False - True - - - - - {3549cd6f-80f8-450f-b99e-cf0a736b1f2a} - WindowsInput - - - {5c3b0b17-cbb7-4b4b-b527-1fab2bb96466} - AgentInterface - - - - - - 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}. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (); -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); -]]> - - - - - - - - + + + + + + + Debug + AnyCPU + {E9A365D5-AEBE-4AF3-86C5-D17BC65ADE46} + Exe + Properties + UlteriusServer + Ulterius Server + v4.6.1 + 512 + + + + false + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + true + false + true + + + AnyCPU + true + full + true + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + 7 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + 7 + false + true + + + + + + app.manifest + + + 256.ico + + + + + + false + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Form + + + AboutBox.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + True + Resources.resx + + + + + + + + + + + + + + + + + + AboutBox.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + + + False + .NET Framework 3.5 SP1 + false + + + + + + + + + + + + + + + + + + ..\packages\AForge.2.2.5\lib\AForge.dll + True + + + ..\packages\AForge.Imaging.2.2.5\lib\AForge.Imaging.dll + True + + + ..\packages\AForge.Math.2.2.5\lib\AForge.Math.dll + True + + + ..\packages\AForge.Video.2.2.5\lib\AForge.Video.dll + True + + + ..\packages\AForge.Video.DirectShow.2.2.5\lib\AForge.Video.DirectShow.dll + True + + + ..\packages\AForge.Vision.2.2.5\lib\AForge.Vision.dll + True + + + ..\packages\BouncyCastle.1.8.1\lib\BouncyCastle.Crypto.dll + True + + + ..\packages\deniszykov.WebSocketListener.4.0.0\lib\net45\deniszykov.WebSocketListener.dll + + + ..\packages\DotNetZip.1.10.1\lib\net20\DotNetZip.dll + True + + + ..\packages\log4net.2.0.8\lib\net45-full\log4net.dll + + + ..\packages\Magnum.2.1.3\lib\NET40\Magnum.dll + True + + + ..\packages\MassTransit.2.9.0\lib\net40\MassTransit.dll + True + + + ..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.3\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll + True + + + ..\packages\JonSkeet.MiscUtil.0.2.0\lib\net35\MiscUtil.dll + + + ..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.dll + True + + + ..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Mdb.dll + True + + + ..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Pdb.dll + True + + + ..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Rocks.dll + True + + + ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll + + + ..\packages\Open.NAT.2.1.0.0\lib\net45\Open.Nat.dll + True + + + ..\Deps\OpenHardwareMonitorLib.dll + + + + ..\packages\SharpDX.4.0.1\lib\net45\SharpDX.dll + + + ..\packages\SharpDX.Direct3D11.4.0.1\lib\net45\SharpDX.Direct3D11.dll + + + ..\packages\SharpDX.DXGI.4.0.1\lib\net45\SharpDX.DXGI.dll + + + ..\packages\SharpDX.Mathematics.4.0.1\lib\net45\SharpDX.Mathematics.dll + + + + + + + + + + False + C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\3.0\System.Management.Automation.dll + + + + + + + ..\packages\System.Threading.Tasks.Dataflow.4.8.0\lib\netstandard2.0\System.Threading.Tasks.Dataflow.dll + + + + + + + + ..\packages\Topshelf.4.0.3\lib\net452\Topshelf.dll + True + + + ..\packages\TurboJpegWrapper.1.4.2.6\lib\net35\TurboJpegWrapper.dll + + + + ..\packages\ZetaLongPaths.1.0.0.19\lib\net40-full\ZetaLongPaths.dll + + + + + {58FBCF7C-E7A9-467C-80B3-FC65E8FCCA08} + 1 + 0 + 0 + tlbimp + False + True + + + + + {3549cd6f-80f8-450f-b99e-cf0a736b1f2a} + WindowsInput + + + {686ae4c4-791f-45eb-9414-029d6115905d} + UlteriusAgent + + + + + + 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}. + + + + + + + + + + + + + + + + + + + + + + \ 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 @@ + + CSharp70 \ 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 @@ -6,7 +6,7 @@ #endregion -namespace AgentInterface.Settings +namespace UlteriusServer.Utilities { public class AppEnvironment { 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 @@ -6,7 +6,7 @@ #endregion -namespace AgentInterface.Settings +namespace UlteriusServer.Utilities { public class Config { 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 @@ -8,7 +8,6 @@ using System.Threading.Tasks; using System.Windows.Forms; using System.Windows.Threading; -using AgentInterface.Settings; using Newtonsoft.Json; #endregion 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 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 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().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 -{ - /// - /// Enum FormatTokenFlags - /// - public enum FormatTokenFlags - { - /// - /// Uses the specifier token as the replacement token, matches '%' but not '%%' - /// - SpecifierToken, - - /// - /// Like String.Format - /// - IndexToken, - - /// - /// Extracts an Object's Members by name. - /// - MemberToken - } - - /// - /// Class StringExtensions - /// - 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; - } - - /// - /// Implement's VB's Like operator logic. - /// - 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 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); - } - - /// - /// 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. - /// - /// Character list string - private static HashSet CharListToSet(string charList) - { - HashSet set = new HashSet(); - - 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; - } - - /// - /// Returns a Secure string from the source string - /// - /// - /// - 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); - } - } - - - /// - /// The Reformatting function called to format the string with a list of arguments. - /// - private static Func, string, IList, string> _regexReformatter; - - /// - /// The Regex which matches the specifier token in strings. - /// - private static Regex _specifierTokenRegex; - - /// - /// The Regex which matches parameter indexes in strings, same as string.Format. - /// - private static Regex _argumentIndexRegex; - - /// - /// The Regex which matches object member names in strings. - /// - private static Regex _objectMemberRegex; - - /// - /// Splits a string into an array of strings, the string is split by commas. - /// - /// The string instance to split by commas. - /// The string that has been comma separated into substrings. - public static string[] CommaSeparate(this string @this) - { - return @this.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); - } - - /// - /// Determines whether two String objects contain the same data, ignoring the case of the letters in the String; uses - /// Ordinal comparison. - /// - /// The current string to be compared to. - /// The other string to compare against the current String for equality. - /// true if the two strings are equal, false otherwise - 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; - } - - - /// - /// Replaces one or more format items in a specified string with the string representation of a specified object. - /// - /// - /// A copy of in which any format items are replaced by the string representation of - /// . - /// - /// A composite format string. - /// The arguments to use in formatting . - 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(); - } - } - - /// - /// The Function which does all the heavy lifting. - /// - /// A composite format string - /// The flags which specify how the string should be interpreted. - /// The arguments to format the parameter with. - /// System.String. - 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(@"(?(\{))+(?[\w\.]+)(?(\}))+", regexOptions); - _specifierTokenRegex = new Regex(@"(? - { - var argumentCollection = new List(); - 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 +{ + /// + /// Enum FormatTokenFlags + /// + public enum FormatTokenFlags + { + /// + /// Uses the specifier token as the replacement token, matches '%' but not '%%' + /// + SpecifierToken, + + /// + /// Like String.Format + /// + IndexToken, + + /// + /// Extracts an Object's Members by name. + /// + MemberToken + } + + /// + /// Class StringExtensions + /// + 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; + } + + /// + /// Implement's VB's Like operator logic. + /// + 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); + } + /// + /// Checks if a string is a valid email + /// + /// + /// + public static bool IsValidEmail(this string email) + { + try + { + var addr = new System.Net.Mail.MailAddress(email); + return addr.Address == email; + } + catch + { + return false; + } + } + + /// + /// Returns true if starts with the path . + /// 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"). + /// + 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); + } + + /// + /// Returns with the minimal concatenation of (starting from end) that + /// results in satisfying .EndsWith(ending). + /// + /// "hel".WithEnding("llo") returns "hello", which is the result of "hel" + "lo". + 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; + } + + /// Gets the rightmost characters from a string. + /// The string to retrieve the substring from. + /// The number of characters to retrieve. + /// The substring. + 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; + } + + /// + /// 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. + /// + /// Character list string + private static HashSet CharListToSet(string charList) + { + var set = new HashSet(); + + 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; + } + + /// + /// Returns a Secure string from the source string + /// + /// + /// + 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); + } + } + + + /// + /// The Reformatting function called to format the string with a list of arguments. + /// + private static Func, string, IList, string> _regexReformatter; + + /// + /// The Regex which matches the specifier token in strings. + /// + private static Regex _specifierTokenRegex; + + /// + /// The Regex which matches parameter indexes in strings, same as string.Format. + /// + private static Regex _argumentIndexRegex; + + /// + /// The Regex which matches object member names in strings. + /// + private static Regex _objectMemberRegex; + + /// + /// Splits a string into an array of strings, the string is split by commas. + /// + /// The string instance to split by commas. + /// The string that has been comma separated into substrings. + public static string[] CommaSeparate(this string @this) + { + return @this.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); + } + + /// + /// Determines whether two String objects contain the same data, ignoring the case of the letters in the String; uses + /// Ordinal comparison. + /// + /// The current string to be compared to. + /// The other string to compare against the current String for equality. + /// true if the two strings are equal, false otherwise + 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; + } + + + /// + /// Replaces one or more format items in a specified string with the string representation of a specified object. + /// + /// + /// A copy of in which any format items are replaced by the string representation of + /// . + /// + /// A composite format string. + /// The arguments to use in formatting . + 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(); + } + } + + /// + /// The Function which does all the heavy lifting. + /// + /// A composite format string + /// The flags which specify how the string should be interpreted. + /// The arguments to format the parameter with. + /// System.String. + 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(@"(?(\{))+(?[\w\.]+)(?(\}))+", regexOptions); + _specifierTokenRegex = new Regex(@"(? + { + var argumentCollection = new List(); + 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 @@ -3,8 +3,9 @@ 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 @@ -48,7 +49,7 @@ private static bool AuthMacOs(string password) return false; } } - + public static LoginInformation AuthWindows(string username, string password) { var info = new LoginInformation(); @@ -56,6 +57,10 @@ public static LoginInformation AuthWindows(string username, string password) { var domainName = Environment.UserDomainName; + if (username.IsValidEmail()) + { + domainName = "MicrosoftAccount"; + } if (username.Contains("\\")) { var splitName = username.Split('\\'); 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 @@ -15,12 +15,12 @@ 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; @@ -82,17 +82,14 @@ public static void RestartDaemon() 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) { - - + // } } @@ -111,17 +108,11 @@ public static void RestartAgent() } 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); @@ -343,10 +334,7 @@ public static void ConfigureServer() { Console.WriteLine("Logs Ready"); } - if (!RunningAsService()) - { - ScreenData.SetupDuplication(); - } + ScreenData.SetupDuplication(); if (Config.Empty) { if (RunningPlatform() == Platform.Windows) @@ -361,15 +349,7 @@ public static void ConfigureServer() 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"); @@ -399,17 +379,17 @@ private static void OpenFirewallForProgram(string exeFileName, string displayNam { 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(); } 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 @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; using System.IO; -using AgentInterface.Settings; using UlteriusServer.Utilities.Extensions; #endregion 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 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("guid", GetMachineGuid()), - new KeyValuePair("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 @@ -10,7 +10,7 @@ using AForge.Video; using AForge.Video.DirectShow; using AForge.Vision.Motion; -using AgentInterface.Settings; +using UlteriusServer.Utilities; #endregion 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 @@ -9,10 +9,11 @@ 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; @@ -286,13 +287,19 @@ var indexFile in } 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; 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 @@ -26,30 +26,22 @@ namespace UlteriusServer.WebSocketAPI public class WebSocketEventListener : IDisposable { - private readonly List _listeners = new List(); + private WebSocketListener _listener; - public WebSocketEventListener(List endpoints) + public WebSocketEventListener(Uri[] endpoints) : this(endpoints, new WebSocketListenerOptions()) { } - public WebSocketEventListener(List 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; @@ -58,21 +50,15 @@ public void Dispose() 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) @@ -95,10 +81,7 @@ private async Task HandleListners(WebSocketListener listener) private void ListenAsync() { - foreach (var listener in _listeners) - { - Task.Run(() => HandleListners(listener)); - } + Task.Run(() => HandleListners(_listener)); } private async Task HandleWebSocketAsync(WebSocket websocket) 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 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + 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 @@ - - - - - WindowsInput - AgentInterface - Newtonsoft.Json - - - \ 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 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 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 GetDisplayInformation() - { - return Display.DisplayInformation(); - } - - - public List 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(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.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 @@ - - - - - Debug - AnyCPU - {686AE4C4-791F-45EB-9414-029D6115905D} - Exe - Properties - UlteriusAgent - UlteriusAgent - v4.5.2 - 512 - true - - - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - - - - - - app.manifest - - - - - - - - - - - - - - - - - - Designer - - - - - - - - - {3549cd6f-80f8-450f-b99e-cf0a736b1f2a} - WindowsInput - - - {5c3b0b17-cbb7-4b4b-b527-1fab2bb96466} - AgentInterface - - - - - - - - - - - - - - - (); -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); -]]> - - - - - - + + + + + Debug + AnyCPU + {686AE4C4-791F-45EB-9414-029D6115905D} + Exe + Properties + UlteriusAgent + UlteriusAgent + v4.6.1 + 512 + true + + + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + 7 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + false + 7 + + + + + + app.manifest + + + + + + ..\packages\Topshelf.4.0.3\lib\net452\Topshelf.dll + + + ..\packages\Warden.NET.1.2.3\lib\net45\Warden.dll + True + + + + + + + + + + Designer + + + + + \ 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 @@ + + + + + \ 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