Migrated Remotely_Library to .NET Standard. Refactored tuples to typed class.

This commit is contained in:
Jared Goodwin 2019-04-04 16:40:54 -07:00
parent 7e180ddfb2
commit 328b987117
44 changed files with 95 additions and 2402 deletions

View File

@ -35,7 +35,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Remotely_Desktop", "Remotel
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Remotely_ScreenCast.Linux", "Remotely_ScreenCast.Linux\Remotely_ScreenCast.Linux.csproj", "{E46F11D0-3C88-4D43-8CCC-EE7182CAD5C1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Remotely_ScreenCast.Core", "Remotely_ScreenCast.Core\Remotely_ScreenCast.Core.csproj", "{B04A1728-2E87-491E-BC7F-F575A1754DEF}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Remotely_ScreenCast.Core", "Remotely_ScreenCast.Core\Remotely_ScreenCast.Core.csproj", "{B04A1728-2E87-491E-BC7F-F575A1754DEF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution

View File

@ -1,7 +1,5 @@
using Remotely_Agent.Services;
using Remotely_Library.Services;
using Remotely_Library.Win32;
using Remotely_Library.Win32_Classes;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;

View File

@ -1,7 +1,5 @@
using Remotely_Library.Models;
using Remotely_Library.Services;
using Remotely_Library.Win32;
using Remotely_Library.Win32_Classes;
using Microsoft.AspNetCore.SignalR.Client;
using Newtonsoft.Json;
using System;
@ -14,6 +12,7 @@ using System.Text;
using System.Threading.Tasks;
using System.Timers;
using System.Reflection;
using Remotely_Library.Win32;
namespace Remotely_Agent.Services
{

View File

@ -134,6 +134,10 @@
<Resource Include="favicon.ico" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Remotely_Library\Remotely_Library.csproj">
<Project>{a9e1ba7a-6080-4dac-9b29-6dc8437150ea}</Project>
<Name>Remotely_Library</Name>
</ProjectReference>
<ProjectReference Include="..\Remotely_ScreenCast.Core\Remotely_ScreenCast.Core.csproj">
<Project>{b04a1728-2e87-491e-bc7f-f575a1754def}</Project>
<Name>Remotely_ScreenCast.Core</Name>

View File

@ -1,5 +1,6 @@
using Remotely_Desktop.Controls;
using Remotely_Desktop.Services;
using Remotely_Library.Models;
using Remotely_ScreenCast.Core;
using Remotely_ScreenCast.Core.Capture;
using Remotely_ScreenCast.Core.Models;
@ -150,11 +151,11 @@ namespace Remotely_Desktop.ViewModels
await Conductor?.OutgoingMessages?.SendCursorChange(cursor, Conductor.Viewers.Keys.ToList());
}
}
private void ScreenCastRequested(object sender, Tuple<string, string> viewerAndRequester)
private void ScreenCastRequested(object sender, ScreenCastRequest screenCastRequest)
{
App.Current.Dispatcher.Invoke(() =>
{
var result = MessageBox.Show($"You've received a connection request from {viewerAndRequester.Item2}. Accept?", "Connection Request", MessageBoxButton.YesNo, MessageBoxImage.Question);
var result = MessageBox.Show($"You've received a connection request from {screenCastRequest.RequesterName}. Accept?", "Connection Request", MessageBoxButton.YesNo, MessageBoxImage.Question);
if (result == MessageBoxResult.Yes)
{
Task.Run(async() =>
@ -177,8 +178,8 @@ namespace Remotely_Desktop.ViewModels
Logger.Write(ex);
capturer = new BitBltCapture();
}
await Conductor.OutgoingMessages.SendCursorChange(CursorIconWatcher.GetCurrentCursor(), new List<string>() { viewerAndRequester.Item1 });
ScreenCaster.BeginScreenCasting(viewerAndRequester.Item1, viewerAndRequester.Item2, capturer, Conductor);
await Conductor.OutgoingMessages.SendCursorChange(CursorIconWatcher.GetCurrentCursor(), new List<string>() { screenCastRequest.ViewerID });
ScreenCaster.BeginScreenCasting(screenCastRequest.ViewerID, screenCastRequest.RequesterName, capturer, Conductor);
});
}
});

View File

@ -6,7 +6,6 @@ using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Management;
using System.Runtime.InteropServices;
namespace Remotely_Library.Models

View File

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Management.Automation;
using System.Text;
namespace Remotely_Library.Models

View File

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Management.Automation;
using System.Text;
namespace Remotely_Library.Models

View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Remotely_Library.Models
{
public class ScreenCastRequest
{
public string ViewerID { get; set; }
public string RequesterName { get; set; }
}
}

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<TargetFramework>netstandard2.0</TargetFramework>
<Platforms>AnyCPU;x86;x64</Platforms>
</PropertyGroup>
@ -19,11 +19,9 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="2.2.0" />
<PackageReference Include="Microsoft.Management.Infrastructure" Version="1.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
<PackageReference Include="System.Management.Automation" Version="6.1.3" />
</ItemGroup>
<ItemGroup>

View File

@ -4,7 +4,7 @@ using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security;
namespace Remotely_Library.Win32_Classes
namespace Remotely_Library.Win32
{
public static class ADVAPI32
{

View File

@ -5,7 +5,7 @@ using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Win32
namespace Remotely_Library.Win32
{
public static class GDI32
{

View File

@ -1,7 +1,7 @@
using System;
using System.Runtime.InteropServices;
namespace Remotely_Library.Win32_Classes
namespace Remotely_Library.Win32
{
public static class Kernel32
{

View File

@ -3,7 +3,7 @@ using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using Microsoft.Win32.SafeHandles;
using System.Runtime.ConstrainedExecution;
using Remotely_Library.Win32_Classes;
using Remotely_Library.Win32;
public static class SECUR32
{

View File

@ -5,7 +5,7 @@ using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Text;
namespace Remotely_Library.Win32_Classes
namespace Remotely_Library.Win32
{
public static class User32
{
@ -63,6 +63,12 @@ namespace Remotely_Library.Win32_Classes
XDOWN = 0x0080,
XUP = 0x0100
}
public enum MonitorState
{
MonitorStateOn = -1,
MonitorStateOff = 2,
MonitorStateStandBy = 1
}
[Flags]
public enum KEYEVENTF : uint
{
@ -1126,7 +1132,7 @@ namespace Remotely_Library.Win32_Classes
[DllImport("user32.dll")]
public static extern bool EnumDesktopsA(IntPtr hwinsta, EnumDesktopsDelegate lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr OpenInputDesktop(uint dwFlags, bool fInherit, ACCESS_MASK dwDesiredAccess);
@ -1238,6 +1244,9 @@ namespace Remotely_Library.Win32_Classes
[DllImport("user32.dll")]
public static extern short VkKeyScan(char ch);
[DllImport("user32.dll")]
public static extern int SendMessage(int hWnd, int hMsg, int wParam, int lParam);
#endregion
}
}

View File

@ -1,7 +1,7 @@
using System;
using System.Runtime.InteropServices;
namespace Remotely_Library.Win32_Classes
namespace Remotely_Library.Win32
{
public static class WTSAPI32
{

View File

@ -1,12 +1,12 @@
using Remotely_Library.Win32_Classes;
using Remotely_Library.Win32;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using static Remotely_Library.Win32_Classes.ADVAPI32;
using static Remotely_Library.Win32_Classes.User32;
using static Remotely_Library.Win32.ADVAPI32;
using static Remotely_Library.Win32.User32;
namespace Remotely_Library.Win32
{
@ -65,14 +65,14 @@ namespace Remotely_Library.Win32
// user input. To remedy this we set the lpDesktop parameter to indicate we want to enable user
// interaction with the new process.
STARTUPINFO si = new STARTUPINFO();
si.cb = (int)Marshal.SizeOf(si);
si.cb = Marshal.SizeOf(si);
si.lpDesktop = @"winsta0\" + desktopName;
// Flags that specify the priority and creation method of the process.
uint dwCreationFlags;
if (hiddenWindow)
{
dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW;
dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW | DETACHED_PROCESS;
}
else
{
@ -120,81 +120,6 @@ namespace Remotely_Library.Win32
{
return User32.OpenInputDesktop(0, false, ACCESS_MASK.GENERIC_ALL);
}
public static void SendLeftMouseDown(int x, int y)
{
mouse_event(MOUSEEVENTF_LEFTDOWN, (uint)x, (uint)y, 0, GetMessageExtraInfo());
}
public static void SendLeftMouseUp(int x, int y)
{
mouse_event(MOUSEEVENTF_LEFTUP, (uint)x, (uint)y, 0, GetMessageExtraInfo());
}
public static void SendRightMouseDown(int x, int y)
{
mouse_event(MOUSEEVENTF_RIGHTDOWN, (uint)x, (uint)y, 0, GetMessageExtraInfo());
}
public static void SendRightMouseUp(int x, int y)
{
mouse_event(MOUSEEVENTF_RIGHTUP, (uint)x, (uint)y, 0, GetMessageExtraInfo());
}
// Offsets are used in case there's a multi-monitor setup where the left-most or top-most edge of the virtual screen
// is not 0. The coordinates sent from the web viewer are always zero-based, so the offset must be applied.
public static uint SendMouseMove(double x, double y)
{
// Coordinates must be normalized. The bottom-right coordinate is mapped to 65535.
var normalizedX = x * (double)65535;
var normalizedY = y * (double)65535;
var union = new InputUnion() { mi = new MOUSEINPUT() { dwFlags = MOUSEEVENTF.ABSOLUTE | MOUSEEVENTF.MOVE | MOUSEEVENTF.VIRTUALDESK, dx = (int)normalizedX, dy = (int)normalizedY, time = 0, mouseData = 0, dwExtraInfo = (UIntPtr)GetMessageExtraInfo() } };
var input = new INPUT() { type = InputType.MOUSE, U = union };
return SendInput(1, new INPUT[] { input }, INPUT.Size);
}
public static uint SendMouseWheel(int deltaY)
{
if (deltaY < 0)
{
deltaY = -120;
}
else if (deltaY > 0)
{
deltaY = 120;
}
var union = new User32.InputUnion() { mi = new User32.MOUSEINPUT() { dwFlags = MOUSEEVENTF.WHEEL, dx = 0, dy = 0, time = 0, mouseData = deltaY, dwExtraInfo = GetMessageExtraInfo() } };
var input = new User32.INPUT() { type = InputType.MOUSE, U = union };
return SendInput(1, new User32.INPUT[] { input }, INPUT.Size);
}
public static void SendKeyDown(VirtualKey key)
{
var union = new InputUnion()
{
ki = new KEYBDINPUT()
{
wVk = key,
wScan = 0,
time = 0,
dwExtraInfo = GetMessageExtraInfo()
}
};
var input = new INPUT() { type = InputType.KEYBOARD, U = union };
SendInput(1, new INPUT[] { input }, INPUT.Size);
}
public static void SendKeyUp(VirtualKey key)
{
var union = new InputUnion()
{
ki = new KEYBDINPUT()
{
wVk = key,
wScan = 0,
time = 0,
dwFlags = KEYEVENTF.KEYUP,
dwExtraInfo = GetMessageExtraInfo()
}
};
var input = new INPUT() { type = InputType.KEYBOARD, U = union };
SendInput(1, new INPUT[] { input }, INPUT.Size);
}
public static string GetCurrentDesktop()
{
var inputDesktop = OpenInputDesktop();
@ -203,33 +128,16 @@ namespace Remotely_Library.Win32
var success = GetUserObjectInformationW(inputDesktop, UOI_NAME, deskBytes, 256, out lenNeeded);
if (!success)
{
return "default";
CloseDesktop(inputDesktop);
return "Default";
}
string deskName;
deskName = Encoding.Unicode.GetString(deskBytes.Take((int)lenNeeded).ToArray()).Replace("\0", "");
var desktopName = Encoding.Unicode.GetString(deskBytes.Take((int)lenNeeded).ToArray()).Replace("\0", "");
CloseDesktop(inputDesktop);
return deskName;
return desktopName;
}
// Remove trailing empty bytes in the buffer.
private static byte[] TrimBytes(byte[] bytes)
public static void SetMonitorState(MonitorState state)
{
// Loop backwards through array until the first non-zero byte is found.
var firstZero = 0;
for (int i = bytes.Length - 1; i >= 0; i--)
{
if (bytes[i] != 0)
{
firstZero = i + 1;
break;
}
}
if (firstZero == 0)
{
throw new Exception("Byte array is empty.");
}
// Return non-empty bytes.
return bytes.Take(firstZero).ToArray();
User32.SendMessage(0xFFFF, 0x112, 0xF170, (int)state);
}
}
}

View File

@ -1,5 +1,6 @@
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.DependencyInjection;
using Remotely_Library.Models;
using Remotely_ScreenCast.Core.Enums;
using Remotely_ScreenCast.Core.Input;
using Remotely_ScreenCast.Core.Models;
@ -16,9 +17,9 @@ namespace Remotely_ScreenCast.Core
{
public class Conductor
{
public event EventHandler<Tuple<string, string>> ScreenCastInitiated;
public event EventHandler<ScreenCastRequest> ScreenCastInitiated;
public event EventHandler<Tuple<string, string>> ScreenCastRequested;
public event EventHandler<ScreenCastRequest> ScreenCastRequested;
public event EventHandler<string> SessionIDChanged;
@ -98,14 +99,19 @@ namespace Remotely_ScreenCast.Core
timer.Start();
}
internal void InvokeScreenCastInitiated(Tuple<string, string> viewerIdAndRequesterName)
internal void InvokeScreenCastInitiated(ScreenCastRequest viewerIdAndRequesterName)
{
ScreenCastInitiated?.Invoke(null, viewerIdAndRequesterName);
}
internal void InvokeScreenCastRequested(Tuple<string, string> viewerIdAndRequesterName)
internal void InvokeScreenCastRequested(ScreenCastRequest viewerIdAndRequesterName)
{
ScreenCastRequested?.Invoke(null, viewerIdAndRequesterName);
}
internal void InvokeSessionIDChanged(string sessionID)
{
SessionIDChanged?.Invoke(null, sessionID);
}
internal void InvokeViewerAdded(Viewer viewer)
{
ViewerAdded?.Invoke(null, viewer);
@ -114,10 +120,5 @@ namespace Remotely_ScreenCast.Core
{
ViewerRemoved?.Invoke(null, viewerID);
}
internal void InvokeSessionIDChanged(string sessionID)
{
SessionIDChanged?.Invoke(null, sessionID);
}
}
}

View File

@ -1,24 +0,0 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Remotely_ScreenCast.Core.Models
{
public class CursorInfo
{
public CursorInfo(byte[] imageBytes, Point hotspot, string cssOverride = null)
{
ImageBytes = imageBytes;
HotSpot = hotspot;
CssOverride = cssOverride;
}
public byte[] ImageBytes { get; set; }
public Point HotSpot { get; set; }
public string CssOverride { get; set; }
}
}

View File

@ -1,5 +0,0 @@
interface CursorInfo {
ImageBytes: any[];
HotSpot: any;
CssOverride: string;
}

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
@ -23,4 +23,8 @@
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Remotely_Library\Remotely_Library.csproj" />
</ItemGroup>
</Project>

View File

@ -12,6 +12,7 @@ using System.IO;
using System.Diagnostics;
using Remotely_ScreenCast.Core.Models;
using Remotely_ScreenCast.Core.Input;
using Remotely_Library.Models;
namespace Remotely_ScreenCast.Core.Sockets
{
@ -30,7 +31,7 @@ namespace Remotely_ScreenCast.Core.Sockets
{
try
{
conductor.InvokeScreenCastInitiated(new Tuple<string, string>(viewerID, requesterName));
conductor.InvokeScreenCastInitiated(new ScreenCastRequest() { ViewerID = viewerID, RequesterName = requesterName });
}
catch (Exception ex)
{
@ -40,7 +41,7 @@ namespace Remotely_ScreenCast.Core.Sockets
hubConnection.On("RequestScreenCast", (string viewerID, string requesterName) =>
{
conductor.InvokeScreenCastRequested(new Tuple<string, string>(viewerID, requesterName));
conductor.InvokeScreenCastRequested(new ScreenCastRequest() { ViewerID = viewerID, RequesterName = requesterName });
});
hubConnection.On("KeyDown", (string key, string viewerID) =>

View File

@ -1,4 +1,5 @@
using Microsoft.AspNetCore.SignalR.Client;
using Remotely_Library.Models;
using Remotely_ScreenCast.Core.Models;
using System;
using System.Collections.Concurrent;

View File

@ -1,4 +1,5 @@
using Remotely_ScreenCast.Core;
using Remotely_Library.Models;
using Remotely_ScreenCast.Core;
using Remotely_ScreenCast.Core.Capture;
using Remotely_ScreenCast.Core.Utilities;
using Remotely_ScreenCast.Linux.Capture;
@ -41,13 +42,13 @@ namespace Remotely_ScreenCast.Linux
}
}
private static async void ScreenCastInitiated(object sender, Tuple<string, string> viewerAndRequester)
private static async void ScreenCastInitiated(object sender, ScreenCastRequest screenCastRequest)
{
try
{
var capturer = new X11Capture(Display);
await Conductor.OutgoingMessages.SendCursorChange(new Core.Models.CursorInfo(null, Point.Empty, "default"), new List<string>() { viewerAndRequester.Item1 });
ScreenCaster.BeginScreenCasting(viewerAndRequester.Item1, viewerAndRequester.Item2, capturer, Conductor);
await Conductor.OutgoingMessages.SendCursorChange(new CursorInfo(null, Point.Empty, "default"), new List<string>() { screenCastRequest.ViewerID });
ScreenCaster.BeginScreenCasting(screenCastRequest.ViewerID, screenCastRequest.RequesterName, capturer, Conductor);
}
catch (Exception ex)
{

View File

@ -19,6 +19,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Remotely_Library\Remotely_Library.csproj" />
<ProjectReference Include="..\Remotely_ScreenCast.Core\Remotely_ScreenCast.Core.csproj" />
</ItemGroup>

View File

@ -5,7 +5,6 @@ using System.IO;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Forms;
using Win32;
using System.Linq;
using System.Threading.Tasks;
using System.Collections.Generic;

View File

@ -11,7 +11,8 @@ using System.Text;
using System.Threading.Tasks;
using System.Timers;
using System.Windows.Forms;
using Win32;
using Remotely_Library.Win32;
using Remotely_Library.Models;
namespace Remotely_ScreenCast.Win.Capture
{

View File

@ -10,7 +10,6 @@ using System.Drawing.Imaging;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using Win32;
namespace Remotely_ScreenCast.Win.Capture
{

View File

@ -1,8 +1,8 @@
using Remotely_ScreenCast.Core.Input;
using Remotely_ScreenCast.Core.Models;
using System;
using Win32;
using static Win32.User32;
using Remotely_Library.Win32;
using static Remotely_Library.Win32.User32;
namespace Remotely_ScreenCast.Win.Input
{

View File

@ -1,5 +1,6 @@
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.DependencyInjection;
using Remotely_Library.Models;
using Remotely_ScreenCast.Core;
using Remotely_ScreenCast.Core.Capture;
using Remotely_ScreenCast.Core.Enums;
@ -19,7 +20,7 @@ using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Win32;
using Remotely_Library.Win32;
namespace Remotely_ScreenCast.Win
{
@ -69,7 +70,7 @@ namespace Remotely_ScreenCast.Win
}
}
private static async void ScreenCastInitiated(object sender, Tuple<string, string> viewerAndRequester)
private static async void ScreenCastInitiated(object sender, ScreenCastRequest screenCastRequest)
{
ICapturer capturer;
try
@ -89,8 +90,8 @@ namespace Remotely_ScreenCast.Win
Logger.Write(ex);
capturer = new BitBltCapture();
}
await Conductor.OutgoingMessages.SendCursorChange(CursorIconWatcher.GetCurrentCursor(), new List<string>() { viewerAndRequester.Item1 });
ScreenCaster.BeginScreenCasting(viewerAndRequester.Item1, viewerAndRequester.Item2, capturer, Conductor);
await Conductor.OutgoingMessages.SendCursorChange(CursorIconWatcher.GetCurrentCursor(), new List<string>() { screenCastRequest.ViewerID });
ScreenCaster.BeginScreenCasting(screenCastRequest.ViewerID, screenCastRequest.RequesterName, capturer, Conductor);
}
public static async void CursorIconWatcher_OnChange(object sender, CursorInfo cursor)

View File

@ -157,13 +157,6 @@
<Compile Include="Input\WinInput.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Win32\ADVAPI32.cs" />
<Compile Include="Win32\GDI32.cs" />
<Compile Include="Win32\Kernel32.cs" />
<Compile Include="Win32\SECUR32.cs" />
<Compile Include="Win32\User32.cs" />
<Compile Include="Win32\Win32Interop.cs" />
<Compile Include="Win32\WTSAPI32.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
@ -173,6 +166,10 @@
<Content Include="FodyWeavers.xml" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Remotely_Library\Remotely_Library.csproj">
<Project>{a9e1ba7a-6080-4dac-9b29-6dc8437150ea}</Project>
<Name>Remotely_Library</Name>
</ProjectReference>
<ProjectReference Include="..\Remotely_ScreenCast.Core\Remotely_ScreenCast.Core.csproj">
<Project>{b04a1728-2e87-491e-bc7f-f575a1754def}</Project>
<Name>Remotely_ScreenCast.Core</Name>

View File

@ -1,372 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security;
namespace Win32
{
public static class ADVAPI32
{
#region Structs
public struct TOKEN_PRIVILEGES
{
public struct LUID
{
public UInt32 LowPart;
public Int32 HighPart;
}
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct LUID_AND_ATTRIBUTES
{
public LUID Luid;
public UInt32 Attributes;
}
public int PrivilegeCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = ANYSIZE_ARRAY)]
public LUID_AND_ATTRIBUTES[] Privileges;
}
public class USEROBJECTFLAGS
{
public int fInherit = 0;
public int fReserved = 0;
public int dwFlags = 0;
}
[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public int Length;
public IntPtr lpSecurityDescriptor;
public bool bInheritHandle;
}
[StructLayout(LayoutKind.Sequential)]
public struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct STARTUPINFO
{
public Int32 cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public Int32 dwX;
public Int32 dwY;
public Int32 dwXSize;
public Int32 dwYSize;
public Int32 dwXCountChars;
public Int32 dwYCountChars;
public Int32 dwFillAttribute;
public Int32 dwFlags;
public Int16 wShowWindow;
public Int16 cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
#endregion
#region Enums
public enum TOKEN_INFORMATION_CLASS
{
/// <summary>
    /// The buffer receives a TOKEN_USER structure that contains the user account of the token.
    /// </summary>
TokenUser = 1,
/// <summary>
    /// The buffer receives a TOKEN_GROUPS structure that contains the group accounts associated with the token.
    /// </summary>
TokenGroups,
/// <summary>
    /// The buffer receives a TOKEN_PRIVILEGES structure that contains the privileges of the token.
    /// </summary>
TokenPrivileges,
/// <summary>
    /// The buffer receives a TOKEN_OWNER structure that contains the default owner security identifier (SID) for newly created objects.
    /// </summary>
TokenOwner,
/// <summary>
    /// The buffer receives a TOKEN_PRIMARY_GROUP structure that contains the default primary group SID for newly created objects.
    /// </summary>
TokenPrimaryGroup,
/// <summary>
    /// The buffer receives a TOKEN_DEFAULT_DACL structure that contains the default DACL for newly created objects.
    /// </summary>
TokenDefaultDacl,
/// <summary>
    /// The buffer receives a TOKEN_SOURCE structure that contains the source of the token. TOKEN_QUERY_SOURCE access is needed to retrieve this information.
    /// </summary>
TokenSource,
/// <summary>
    /// The buffer receives a TOKEN_TYPE value that indicates whether the token is a primary or impersonation token.
    /// </summary>
TokenType,
/// <summary>
    /// The buffer receives a SECURITY_IMPERSONATION_LEVEL value that indicates the impersonation level of the token. If the access token is not an impersonation token, the function fails.
    /// </summary>
TokenImpersonationLevel,
/// <summary>
    /// The buffer receives a TOKEN_STATISTICS structure that contains various token statistics.
    /// </summary>
TokenStatistics,
/// <summary>
    /// The buffer receives a TOKEN_GROUPS structure that contains the list of restricting SIDs in a restricted token.
    /// </summary>
TokenRestrictedSids,
/// <summary>
    /// The buffer receives a DWORD value that indicates the Terminal Services session identifier that is associated with the token.
    /// </summary>
TokenSessionId,
/// <summary>
    /// The buffer receives a TOKEN_GROUPS_AND_PRIVILEGES structure that contains the user SID, the group accounts, the restricted SIDs, and the authentication ID associated with the token.
    /// </summary>
TokenGroupsAndPrivileges,
/// <summary>
    /// Reserved.
    /// </summary>
TokenSessionReference,
/// <summary>
    /// The buffer receives a DWORD value that is nonzero if the token includes the SANDBOX_INERT flag.
    /// </summary>
TokenSandBoxInert,
/// <summary>
    /// Reserved.
    /// </summary>
TokenAuditPolicy,
/// <summary>
    /// The buffer receives a TOKEN_ORIGIN value.
    /// </summary>
TokenOrigin,
/// <summary>
    /// The buffer receives a TOKEN_ELEVATION_TYPE value that specifies the elevation level of the token.
    /// </summary>
TokenElevationType,
/// <summary>
    /// The buffer receives a TOKEN_LINKED_TOKEN structure that contains a handle to another token that is linked to this token.
    /// </summary>
TokenLinkedToken,
/// <summary>
    /// The buffer receives a TOKEN_ELEVATION structure that specifies whether the token is elevated.
    /// </summary>
TokenElevation,
/// <summary>
    /// The buffer receives a DWORD value that is nonzero if the token has ever been filtered.
    /// </summary>
TokenHasRestrictions,
/// <summary>
    /// The buffer receives a TOKEN_ACCESS_INFORMATION structure that specifies security information contained in the token.
    /// </summary>
TokenAccessInformation,
/// <summary>
    /// The buffer receives a DWORD value that is nonzero if virtualization is allowed for the token.
    /// </summary>
TokenVirtualizationAllowed,
/// <summary>
    /// The buffer receives a DWORD value that is nonzero if virtualization is enabled for the token.
    /// </summary>
TokenVirtualizationEnabled,
/// <summary>
    /// The buffer receives a TOKEN_MANDATORY_LABEL structure that specifies the token's integrity level.
    /// </summary>
TokenIntegrityLevel,
/// <summary>
    /// The buffer receives a DWORD value that is nonzero if the token has the UIAccess flag set.
    /// </summary>
TokenUIAccess,
/// <summary>
    /// The buffer receives a TOKEN_MANDATORY_POLICY structure that specifies the token's mandatory integrity policy.
    /// </summary>
TokenMandatoryPolicy,
/// <summary>
    /// The buffer receives the token's logon security identifier (SID).
    /// </summary>
TokenLogonSid,
/// <summary>
    /// The maximum value for this enumeration
    /// </summary>
MaxTokenInfoClass
}
public enum LOGON_TYPE
{
LOGON32_LOGON_INTERACTIVE = 2,
LOGON32_LOGON_NETWORK,
LOGON32_LOGON_BATCH,
LOGON32_LOGON_SERVICE,
LOGON32_LOGON_UNLOCK = 7,
LOGON32_LOGON_NETWORK_CLEARTEXT,
LOGON32_LOGON_NEW_CREDENTIALS
}
public enum LOGON_PROVIDER
{
LOGON32_PROVIDER_DEFAULT,
LOGON32_PROVIDER_WINNT35,
LOGON32_PROVIDER_WINNT40,
LOGON32_PROVIDER_WINNT50
}
[Flags]
public enum CreateProcessFlags
{
CREATE_BREAKAWAY_FROM_JOB = 0x01000000,
CREATE_DEFAULT_ERROR_MODE = 0x04000000,
CREATE_NEW_CONSOLE = 0x00000010,
CREATE_NEW_PROCESS_GROUP = 0x00000200,
CREATE_NO_WINDOW = 0x08000000,
CREATE_PROTECTED_PROCESS = 0x00040000,
CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000,
CREATE_SEPARATE_WOW_VDM = 0x00000800,
CREATE_SHARED_WOW_VDM = 0x00001000,
CREATE_SUSPENDED = 0x00000004,
CREATE_UNICODE_ENVIRONMENT = 0x00000400,
DEBUG_ONLY_THIS_PROCESS = 0x00000002,
DEBUG_PROCESS = 0x00000001,
DETACHED_PROCESS = 0x00000008,
EXTENDED_STARTUPINFO_PRESENT = 0x00080000,
INHERIT_PARENT_AFFINITY = 0x00010000
}
public enum TOKEN_TYPE : int
{
TokenPrimary = 1,
TokenImpersonation = 2
}
public enum SECURITY_IMPERSONATION_LEVEL : int
{
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 CREATE_NO_WINDOW = 0x08000000;
public const int DETACHED_PROCESS = 0x00000008;
public const int TOKEN_ALL_ACCESS = 0x000f01ff;
public const int PROCESS_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF;
public const int STANDARD_RIGHTS_REQUIRED = 0x000F0000;
public const int SYNCHRONIZE = 0x00100000;
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;
public const UInt32 SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001;
public const UInt32 SE_PRIVILEGE_ENABLED = 0x00000002;
public const UInt32 SE_PRIVILEGE_REMOVED = 0x00000004;
public const UInt32 SE_PRIVILEGE_USED_FOR_ACCESS = 0x80000000;
public const Int32 ANYSIZE_ARRAY = 1;
public const int UOI_FLAGS = 1;
public const int UOI_NAME = 2;
public const int UOI_TYPE = 3;
public const int UOI_USER_SID = 4;
public const int UOI_HEAPSIZE = 5;
public const int UOI_IO = 6;
#endregion
#region DLL Imports
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool AdjustTokenPrivileges(IntPtr tokenHandle,
[MarshalAs(UnmanagedType.Bool)]bool disableAllPrivileges,
ref TOKEN_PRIVILEGES newState,
UInt32 bufferLengthInBytes,
ref TOKEN_PRIVILEGES previousState,
out UInt32 returnLengthInBytes);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool CreateProcessAsUser(
IntPtr hToken,
string lpApplicationName,
string lpCommandLine,
ref SECURITY_ATTRIBUTES lpProcessAttributes,
ref SECURITY_ATTRIBUTES lpThreadAttributes,
bool bInheritHandles,
uint dwCreationFlags,
IntPtr lpEnvironment,
string lpCurrentDirectory,
ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool AllocateLocallyUniqueId(out IntPtr pLuid);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = false)]
public static extern SECUR32.WinErrors LsaNtStatusToWinError(SECUR32.WinStatusCodes status);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool GetTokenInformation(
IntPtr TokenHandle,
SECUR32.TOKEN_INFORMATION_CLASS TokenInformationClass,
IntPtr TokenInformation,
uint TokenInformationLength,
out uint ReturnLength);
[DllImport("advapi32.dll", SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool LogonUser(
[MarshalAs(UnmanagedType.LPStr)] string pszUserName,
[MarshalAs(UnmanagedType.LPStr)] string pszDomain,
[MarshalAs(UnmanagedType.LPStr)] string pszPassword,
int dwLogonType,
int dwLogonProvider,
out IntPtr phToken);
[DllImport("advapi32", SetLastError = true), SuppressUnmanagedCodeSecurityAttribute]
public static extern bool OpenProcessToken(IntPtr ProcessHandle, int DesiredAccess, ref IntPtr TokenHandle);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public extern static bool DuplicateTokenEx(
IntPtr hExistingToken,
uint dwDesiredAccess,
ref SECURITY_ATTRIBUTES lpTokenAttributes,
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
TOKEN_TYPE TokenType,
out IntPtr phNewToken);
[DllImport("advapi32.dll", SetLastError = false)]
public static extern uint LsaNtStatusToWinError(uint status);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool GetUserObjectInformationW(IntPtr hObj, int nIndex,
[Out] byte[] pvInfo, uint nLength, out uint lpnLengthNeeded);
#endregion
}
}

View File

@ -1,24 +0,0 @@
using System;
using System.Runtime.InteropServices;
namespace Win32
{
public static class Kernel32
{
#region DLL Imports
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool CloseHandle(IntPtr hSnapshot);
[DllImport("kernel32.dll")]
public static extern uint WTSGetActiveConsoleSessionId();
[DllImport("kernel32.dll")]
public static extern bool ProcessIdToSessionId(uint dwProcessId, ref uint pSessionId);
[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId);
#endregion
}
}

View File

@ -1,373 +0,0 @@
using System;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using Microsoft.Win32.SafeHandles;
using System.Runtime.ConstrainedExecution;
using Win32;
public static class SECUR32
{
public enum WinStatusCodes : uint
{
STATUS_SUCCESS = 0
}
public enum WinErrors : uint
{
NO_ERROR = 0,
}
public enum WinLogonType
{
LOGON32_LOGON_INTERACTIVE = 2,
LOGON32_LOGON_NETWORK = 3,
LOGON32_LOGON_BATCH = 4,
LOGON32_LOGON_SERVICE = 5,
LOGON32_LOGON_UNLOCK = 7,
LOGON32_LOGON_NETWORK_CLEARTEXT = 8,
LOGON32_LOGON_NEW_CREDENTIALS = 9
}
// SECURITY_LOGON_TYPE
public enum SecurityLogonType
{
Interactive = 2, // Interactively logged on (locally or remotely)
Network, // Accessing system via network
Batch, // Started via a batch queue
Service, // Service started by service controller
Proxy, // Proxy logon
Unlock, // Unlock workstation
NetworkCleartext, // Network logon with cleartext credentials
NewCredentials, // Clone caller, new default credentials
RemoteInteractive, // Remote, yet interactive. Terminal server
CachedInteractive, // Try cached credentials without hitting the net.
CachedRemoteInteractive, // Same as RemoteInteractive, this is used internally for auditing purpose
CachedUnlock // Cached Unlock workstation
}
[StructLayout(LayoutKind.Sequential)]
public struct LSA_UNICODE_STRING
{
public UInt16 Length;
public UInt16 MaximumLength;
public IntPtr Buffer;
}
[StructLayout(LayoutKind.Sequential)]
public struct TOKEN_SOURCE
{
public TOKEN_SOURCE(string name)
{
SourceName = new byte[8];
System.Text.Encoding.GetEncoding(1252).GetBytes(name, 0, name.Length, SourceName, 0);
if (!ADVAPI32.AllocateLocallyUniqueId(out SourceIdentifier))
throw new System.ComponentModel.Win32Exception();
}
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] SourceName;
public IntPtr SourceIdentifier;
}
[StructLayout(LayoutKind.Sequential)]
public struct KERB_INTERACTIVE_LOGON
{
public KERB_LOGON_SUBMIT_TYPE MessageType;
public string LogonDomainName;
public string UserName;
public string Password;
}
public enum KERB_LOGON_SUBMIT_TYPE
{
KerbInteractiveLogon = 2,
KerbSmartCardLogon = 6,
KerbWorkstationUnlockLogon = 7,
KerbSmartCardUnlockLogon = 8,
KerbProxyLogon = 9,
KerbTicketLogon = 10,
KerbTicketUnlockLogon = 11,
KerbS4ULogon = 12,
KerbCertificateLogon = 13,
KerbCertificateS4ULogon = 14,
KerbCertificateUnlockLogon = 15
}
public enum TOKEN_INFORMATION_CLASS
{
/// <summary>
    /// The buffer receives a TOKEN_USER structure that contains the user account of the token.
    /// </summary>
TokenUser = 1,
/// <summary>
    /// The buffer receives a TOKEN_GROUPS structure that contains the group accounts associated with the token.
    /// </summary>
TokenGroups,
/// <summary>
    /// The buffer receives a TOKEN_PRIVILEGES structure that contains the privileges of the token.
    /// </summary>
TokenPrivileges,
/// <summary>
    /// The buffer receives a TOKEN_OWNER structure that contains the default owner security identifier (SID) for newly created objects.
    /// </summary>
TokenOwner,
/// <summary>
    /// The buffer receives a TOKEN_PRIMARY_GROUP structure that contains the default primary group SID for newly created objects.
    /// </summary>
TokenPrimaryGroup,
/// <summary>
    /// The buffer receives a TOKEN_DEFAULT_DACL structure that contains the default DACL for newly created objects.
    /// </summary>
TokenDefaultDacl,
/// <summary>
    /// The buffer receives a TOKEN_SOURCE structure that contains the source of the token. TOKEN_QUERY_SOURCE access is needed to retrieve this information.
    /// </summary>
TokenSource,
/// <summary>
    /// The buffer receives a TOKEN_TYPE value that indicates whether the token is a primary or impersonation token.
    /// </summary>
TokenType,
/// <summary>
    /// The buffer receives a SECURITY_IMPERSONATION_LEVEL value that indicates the impersonation level of the token. If the access token is not an impersonation token, the function fails.
    /// </summary>
TokenImpersonationLevel,
/// <summary>
    /// The buffer receives a TOKEN_STATISTICS structure that contains various token statistics.
    /// </summary>
TokenStatistics,
/// <summary>
    /// The buffer receives a TOKEN_GROUPS structure that contains the list of restricting SIDs in a restricted token.
    /// </summary>
TokenRestrictedSids,
/// <summary>
    /// The buffer receives a DWORD value that indicates the Terminal Services session identifier that is associated with the token.
    /// </summary>
TokenSessionId,
/// <summary>
    /// The buffer receives a TOKEN_GROUPS_AND_PRIVILEGES structure that contains the user SID, the group accounts, the restricted SIDs, and the authentication ID associated with the token.
    /// </summary>
TokenGroupsAndPrivileges,
/// <summary>
    /// Reserved.
    /// </summary>
TokenSessionReference,
/// <summary>
    /// The buffer receives a DWORD value that is nonzero if the token includes the SANDBOX_INERT flag.
    /// </summary>
TokenSandBoxInert,
/// <summary>
    /// Reserved.
    /// </summary>
TokenAuditPolicy,
/// <summary>
    /// The buffer receives a TOKEN_ORIGIN value.
    /// </summary>
TokenOrigin,
/// <summary>
    /// The buffer receives a TOKEN_ELEVATION_TYPE value that specifies the elevation level of the token.
    /// </summary>
TokenElevationType,
/// <summary>
    /// The buffer receives a TOKEN_LINKED_TOKEN structure that contains a handle to another token that is linked to this token.
    /// </summary>
TokenLinkedToken,
/// <summary>
    /// The buffer receives a TOKEN_ELEVATION structure that specifies whether the token is elevated.
    /// </summary>
TokenElevation,
/// <summary>
    /// The buffer receives a DWORD value that is nonzero if the token has ever been filtered.
    /// </summary>
TokenHasRestrictions,
/// <summary>
    /// The buffer receives a TOKEN_ACCESS_INFORMATION structure that specifies security information contained in the token.
    /// </summary>
TokenAccessInformation,
/// <summary>
    /// The buffer receives a DWORD value that is nonzero if virtualization is allowed for the token.
    /// </summary>
TokenVirtualizationAllowed,
/// <summary>
    /// The buffer receives a DWORD value that is nonzero if virtualization is enabled for the token.
    /// </summary>
TokenVirtualizationEnabled,
/// <summary>
    /// The buffer receives a TOKEN_MANDATORY_LABEL structure that specifies the token's integrity level.
    /// </summary>
TokenIntegrityLevel,
/// <summary>
    /// The buffer receives a DWORD value that is nonzero if the token has the UIAccess flag set.
    /// </summary>
TokenUIAccess,
/// <summary>
    /// The buffer receives a TOKEN_MANDATORY_POLICY structure that specifies the token's mandatory integrity policy.
    /// </summary>
TokenMandatoryPolicy,
/// <summary>
    /// The buffer receives the token's logon security identifier (SID).
    /// </summary>
TokenLogonSid,
/// <summary>
    /// The maximum value for this enumeration
    /// </summary>
MaxTokenInfoClass
}
[StructLayout(LayoutKind.Sequential)]
public struct QUOTA_LIMITS
{
UInt32 PagedPoolLimit;
UInt32 NonPagedPoolLimit;
UInt32 MinimumWorkingSetSize;
UInt32 MaximumWorkingSetSize;
UInt32 PagefileLimit;
Int64 TimeLimit;
}
[StructLayout(LayoutKind.Sequential)]
public struct LSA_STRING
{
public UInt16 Length;
public UInt16 MaximumLength;
public /*PCHAR*/ IntPtr Buffer;
}
[DllImport("secur32.dll", SetLastError = true)]
public static extern WinStatusCodes LsaLogonUser(
[In] IntPtr LsaHandle,
[In] ref LSA_STRING OriginName,
[In] SecurityLogonType LogonType,
[In] UInt32 AuthenticationPackage,
[In] IntPtr AuthenticationInformation,
[In] UInt32 AuthenticationInformationLength,
[In] /*PTOKEN_GROUPS*/ IntPtr LocalGroups,
[In] ref TOKEN_SOURCE SourceContext,
[Out] /*PVOID*/ out IntPtr ProfileBuffer,
[Out] out UInt32 ProfileBufferLength,
[Out] out Int64 LogonId,
[Out] out IntPtr Token,
[Out] out QUOTA_LIMITS Quotas,
[Out] out WinStatusCodes SubStatus
);
[DllImport("secur32.dll", SetLastError = true)]
public static extern WinStatusCodes LsaRegisterLogonProcess(
IntPtr LogonProcessName,
out IntPtr LsaHandle,
out ulong SecurityMode
);
[DllImport("secur32.dll", SetLastError = false)]
public static extern WinStatusCodes LsaLookupAuthenticationPackage([In] IntPtr LsaHandle, [In] ref LSA_STRING PackageName, [Out] out UInt32 AuthenticationPackage);
[DllImport("secur32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[ResourceExposure(ResourceScope.None)]
internal static extern int LsaConnectUntrusted(
[In, Out] ref SafeLsaLogonProcessHandle LsaHandle);
[DllImport("secur32.dll", SetLastError = false)]
public static extern WinStatusCodes LsaConnectUntrusted([Out] out IntPtr LsaHandle);
[System.Security.SecurityCritical] // auto-generated
internal sealed class SafeLsaLogonProcessHandle : SafeHandleZeroOrMinusOneIsInvalid
{
private SafeLsaLogonProcessHandle() : base(true) { }
// 0 is an Invalid Handle
internal SafeLsaLogonProcessHandle(IntPtr handle) : base(true)
{
SetHandle(handle);
}
internal static SafeLsaLogonProcessHandle InvalidHandle
{
get { return new SafeLsaLogonProcessHandle(IntPtr.Zero); }
}
[System.Security.SecurityCritical]
override protected bool ReleaseHandle()
{
// LsaDeregisterLogonProcess returns an NTSTATUS
return LsaDeregisterLogonProcess(handle) >= 0;
}
}
[DllImport("secur32.dll", SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[ResourceExposure(ResourceScope.None)]
internal static extern int LsaDeregisterLogonProcess(IntPtr handle);
public static void CreateNewSession()
{
var kli = new SECUR32.KERB_INTERACTIVE_LOGON()
{
MessageType = SECUR32.KERB_LOGON_SUBMIT_TYPE.KerbInteractiveLogon,
UserName = "",
Password = ""
};
IntPtr pluid;
IntPtr lsaHan;
uint authPackID;
IntPtr kerbLogInfo;
SECUR32.LSA_STRING logonProc = new SECUR32.LSA_STRING()
{
Buffer = Marshal.StringToHGlobalAuto("InstaLogon"),
Length = (ushort)Marshal.SizeOf(Marshal.StringToHGlobalAuto("InstaLogon")),
MaximumLength = (ushort)Marshal.SizeOf(Marshal.StringToHGlobalAuto("InstaLogon"))
};
SECUR32.LSA_STRING originName = new SECUR32.LSA_STRING()
{
Buffer = Marshal.StringToHGlobalAuto("InstaLogon"),
Length = (ushort)Marshal.SizeOf(Marshal.StringToHGlobalAuto("InstaLogon")),
MaximumLength = (ushort)Marshal.SizeOf(Marshal.StringToHGlobalAuto("InstaLogon"))
};
SECUR32.LSA_STRING authPackage = new SECUR32.LSA_STRING()
{
Buffer = Marshal.StringToHGlobalAuto("MICROSOFT_KERBEROS_NAME_A"),
Length = (ushort)Marshal.SizeOf(Marshal.StringToHGlobalAuto("MICROSOFT_KERBEROS_NAME_A")),
MaximumLength = (ushort)Marshal.SizeOf(Marshal.StringToHGlobalAuto("MICROSOFT_KERBEROS_NAME_A"))
};
IntPtr hLogonProc = Marshal.AllocHGlobal(Marshal.SizeOf(logonProc));
Marshal.StructureToPtr(logonProc, hLogonProc, false);
ADVAPI32.AllocateLocallyUniqueId(out pluid);
LsaConnectUntrusted(out lsaHan);
//SECUR32.LsaRegisterLogonProcess(hLogonProc, out lsaHan, out secMode);
SECUR32.LsaLookupAuthenticationPackage(lsaHan, ref authPackage, out authPackID);
kerbLogInfo = Marshal.AllocHGlobal(Marshal.SizeOf(kli));
Marshal.StructureToPtr(kli, kerbLogInfo, false);
var ts = new SECUR32.TOKEN_SOURCE("Insta");
IntPtr profBuf;
uint profBufLen;
long logonID;
IntPtr logonToken;
SECUR32.QUOTA_LIMITS quotas;
SECUR32.WinStatusCodes subStatus;
SECUR32.LsaLogonUser(lsaHan, ref originName, SECUR32.SecurityLogonType.Interactive, authPackID, kerbLogInfo, (uint)Marshal.SizeOf(kerbLogInfo), IntPtr.Zero, ref ts, out profBuf, out profBufLen, out logonID, out logonToken, out quotas, out subStatus);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,43 +0,0 @@
using System;
using System.Runtime.InteropServices;
namespace Win32
{
public static class WTSAPI32
{
[StructLayout(LayoutKind.Sequential)]
public struct WTS_SESSION_INFO
{
public Int32 SessionID;
[MarshalAs(UnmanagedType.LPStr)]
public String pWinStationName;
public WTS_CONNECTSTATE_CLASS State;
}
public enum WTS_CONNECTSTATE_CLASS
{
WTSActive,
WTSConnected,
WTSConnectQuery,
WTSShadow,
WTSDisconnected,
WTSIdle,
WTSListen,
WTSReset,
WTSDown,
WTSInit
}
public static IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero;
[DllImport("wtsapi32.dll", SetLastError = true)]
static extern IntPtr WTSOpenServer(string pServerName);
[DllImport("wtsapi32.dll", SetLastError = true)]
public static extern int WTSEnumerateSessions(
System.IntPtr hServer,
int Reserved,
int Version,
ref System.IntPtr ppSessionInfo,
ref int pCount);
}
}

View File

@ -1,144 +0,0 @@
using Win32;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using static Win32.ADVAPI32;
using static Win32.User32;
using System.Windows.Forms;
namespace Win32
{
public class Win32Interop
{
public static bool OpenInteractiveProcess(string applicationName, string desktopName, bool hiddenWindow, out PROCESS_INFORMATION procInfo)
{
uint winlogonPid = 0;
IntPtr hUserTokenDup = IntPtr.Zero, hPToken = IntPtr.Zero, hProcess = IntPtr.Zero;
procInfo = new PROCESS_INFORMATION();
// Obtain session ID for active session.
uint dwSessionId = Kernel32.WTSGetActiveConsoleSessionId();
// Check for RDP session. If active, use that session ID instead.
var rdpSessionID = GetRDPSession();
if (rdpSessionID > 0)
{
dwSessionId = rdpSessionID;
}
// Obtain the process ID of the winlogon process that is running within the currently active session.
Process[] processes = Process.GetProcessesByName("winlogon");
foreach (Process p in processes)
{
if ((uint)p.SessionId == dwSessionId)
{
winlogonPid = (uint)p.Id;
}
}
// Obtain a handle to the winlogon process.
hProcess = Kernel32.OpenProcess(MAXIMUM_ALLOWED, false, winlogonPid);
// Obtain a handle to the access token of the winlogon process.
if (!OpenProcessToken(hProcess, TOKEN_DUPLICATE, ref hPToken))
{
Kernel32.CloseHandle(hProcess);
return false;
}
// Security attibute structure used in DuplicateTokenEx and CreateProcessAsUser.
SECURITY_ATTRIBUTES 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, SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, TOKEN_TYPE.TokenPrimary, out hUserTokenDup))
{
Kernel32.CloseHandle(hProcess);
Kernel32.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.
STARTUPINFO si = new STARTUPINFO();
si.cb = Marshal.SizeOf(si);
si.lpDesktop = @"winsta0\" + desktopName;
// Flags that specify the priority and creation method of the process.
uint dwCreationFlags;
if (hiddenWindow)
{
dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW | DETACHED_PROCESS;
}
else
{
dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
}
// Create a new process in the current user's logon session.
bool result = CreateProcessAsUser(hUserTokenDup, null, applicationName, ref sa, ref sa, false, dwCreationFlags, IntPtr.Zero, null, ref si, out procInfo);
// Invalidate the handles.
Kernel32.CloseHandle(hProcess);
Kernel32.CloseHandle(hPToken);
Kernel32.CloseHandle(hUserTokenDup);
return result;
}
public static uint GetRDPSession()
{
IntPtr ppSessionInfo = IntPtr.Zero;
Int32 count = 0;
Int32 retval = WTSAPI32.WTSEnumerateSessions(WTSAPI32.WTS_CURRENT_SERVER_HANDLE, 0, 1, ref ppSessionInfo, ref count);
Int32 dataSize = Marshal.SizeOf(typeof(WTSAPI32.WTS_SESSION_INFO));
var sessList = new List<WTSAPI32.WTS_SESSION_INFO>();
Int64 current = (Int64)ppSessionInfo;
if (retval != 0)
{
for (int i = 0; i < count; i++)
{
WTSAPI32.WTS_SESSION_INFO sessInf = (WTSAPI32.WTS_SESSION_INFO)Marshal.PtrToStructure((System.IntPtr)current, typeof(WTSAPI32.WTS_SESSION_INFO));
current += dataSize;
sessList.Add(sessInf);
}
}
uint retVal = 0;
var rdpSession = sessList.Find(ses => ses.pWinStationName.ToLower().Contains("rdp") && ses.State == 0);
if (sessList.Exists(ses => ses.pWinStationName.ToLower().Contains("rdp") && ses.State == 0))
{
retVal = (uint)rdpSession.SessionID;
}
return retVal;
}
public static IntPtr OpenInputDesktop()
{
return User32.OpenInputDesktop(0, false, ACCESS_MASK.GENERIC_ALL);
}
public static string GetCurrentDesktop()
{
var inputDesktop = OpenInputDesktop();
byte[] deskBytes = new byte[256];
uint lenNeeded;
var success = GetUserObjectInformationW(inputDesktop, UOI_NAME, deskBytes, 256, out lenNeeded);
if (!success)
{
CloseDesktop(inputDesktop);
return "Default";
}
var desktopName = Encoding.Unicode.GetString(deskBytes.Take((int)lenNeeded).ToArray()).Replace("\0", "");
CloseDesktop(inputDesktop);
return desktopName;
}
public static void SetMonitorState(MonitorState state)
{
User32.SendMessage(0xFFFF, 0x112, 0xF170, (int)state);
}
}
}

View File

@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Management.Automation;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;

View File

@ -1 +1 @@
2019.04.03.2058
2019.04.04.0721

View File

@ -23,7 +23,7 @@ namespace Remotely_Server.Services
public bool RedirectToHTTPS => bool.Parse(Config["ApplicationOptions:RedirectToHTTPS"]);
public bool AllowApiLogin => bool.Parse(Config["ApplicationOptions:AllowApiLogin"]);
public bool UseHSTS => bool.Parse(Config["ApplicationOptions:RedirectToHTTPS"]);
public string[] TrustedCorsOrigins => Config.GetSection("ApplicationOptions:TrustedCorsOrigins").Get<string[]>();
public string SmtpHost => Config["ApplicationOptions:SmtpHost"];
public int SmtpPort => int.Parse(Config["ApplicationOptions:SmtpPort"]);
public string SmtpUserName => Config["ApplicationOptions:SmtpUserName"];

View File

@ -8,7 +8,6 @@ using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Management.Automation;
using System.Threading.Tasks;
namespace Remotely_Server.Services

View File

@ -19,7 +19,7 @@
"DataRetentionInDays": 90,
"RemoteControlSessionLimit": 1,
"AllowApiLogin": false,
"TrustedCorsOrigins": [ ],
"TrustedCorsOrigins": [],
"SmtpHost": "",
"SmtpPort": 25,
"SmtpUserName": "",

File diff suppressed because one or more lines are too long

View File

@ -293,9 +293,9 @@ function deleteInvite(ev: MouseEvent) {
xhr.onerror = () => {
showError(xhr);
}
xhr.open("delete", location.origin + `/api/OrganizationManagement/DeleteInvite/`);
xhr.open("delete", location.origin + `/api/OrganizationManagement/DeleteInvite/${inviteID}`);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(JSON.stringify(inviteID));
xhr.send();
}
function showError(xhr: XMLHttpRequest) {
console.error(xhr);