testing remote stuff

This commit is contained in:
kkb 2023-11-17 17:12:41 +01:00
parent 1e05d4576d
commit 3c9ccaafeb
374 changed files with 10526 additions and 2037 deletions

View file

@ -0,0 +1,140 @@
/*
Copyright 1985, 1986, 1987, 1991, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
*/
using System.Runtime.InteropServices;
namespace Insight.Remote.Shared.Native.Linux;
public static unsafe class LibX11
{
[DllImport("libX11")]
public static extern IntPtr XGetImage(IntPtr display, IntPtr drawable, int x, int y, int width, int height, long plane_mask, int format);
[DllImport("libX11")]
public static extern IntPtr XDefaultVisual(IntPtr display, int screen_number);
[DllImport("libX11")]
public static extern int XScreenCount(IntPtr display);
[DllImport("libX11")]
public static extern int XDefaultScreen(IntPtr display);
[DllImport("libX11")]
public static extern IntPtr XOpenDisplay(string display_name);
[DllImport("libX11")]
public static extern void XCloseDisplay(IntPtr display);
[DllImport("libX11")]
public static extern IntPtr XRootWindow(IntPtr display, int screen_number);
[DllImport("libX11")]
public static extern IntPtr XGetSubImage(IntPtr display, IntPtr drawable, int x, int y, uint width, uint height, ulong plane_mask, int format, IntPtr dest_image, int dest_x, int dest_y);
[DllImport("libX11")]
public static extern IntPtr XScreenOfDisplay(IntPtr display, int screen_number);
[DllImport("libX11")]
public static extern int XDisplayWidth(IntPtr display, int screen_number);
[DllImport("libX11")]
public static extern int XDisplayHeight(IntPtr display, int screen_number);
[DllImport("libX11")]
public static extern int XWidthOfScreen(IntPtr screen);
[DllImport("libX11")]
public static extern int XHeightOfScreen(IntPtr screen);
[DllImport("libX11")]
public static extern IntPtr XDefaultGC(IntPtr display, int screen_number);
[DllImport("libX11")]
public static extern IntPtr XDefaultRootWindow(IntPtr display);
[DllImport("libX11")]
public static extern void XGetInputFocus(IntPtr display, out IntPtr focus_return, out int revert_to_return);
[DllImport("libX11")]
public static extern IntPtr XStringToKeysym(string key);
[DllImport("libX11")]
public static extern uint XKeysymToKeycode(IntPtr display, IntPtr keysym);
[DllImport("libX11")]
public static extern IntPtr XRootWindowOfScreen(IntPtr screen);
[DllImport("libX11")]
public static extern ulong XNextRequest(IntPtr display);
[DllImport("libX11")]
public static extern void XForceScreenSaver(IntPtr display, int mode);
[DllImport("libX11")]
public static extern void XSync(IntPtr display, bool discard);
[DllImport("libX11")]
public static extern void XDestroyImage(IntPtr ximage);
[DllImport("libX11")]
public static extern void XNoOp(IntPtr display);
[DllImport("libX11")]
public static extern void XFree(IntPtr data);
[DllImport("libX11")]
public static extern int XGetWindowAttributes(IntPtr display, IntPtr window, out XWindowAttributes windowAttributes);
public struct XImage
{
public int width;
public int height; /* size of image */
public int xoffset; /* number of pixels offset in X direction */
public int format; /* XYBitmap, XYPixmap, ZPixmap */
//public char* data; /* pointer to image data */
public IntPtr data; /* pointer to image data */
public int byte_order; /* data byte order, LSBFirst, MSBFirst */
public int bitmap_unit; /* quant. of scanline 8, 16, 32 */
public int bitmap_bit_order; /* LSBFirst, MSBFirst */
public int bitmap_pad; /* 8, 16, 32 either XY or ZPixmap */
public int depth; /* depth of image */
public int bytes_per_line; /* accelerator to next scanline */
public int bits_per_pixel; /* bits per pixel (ZPixmap) */
public ulong red_mask; /* bits in z arrangement */
public ulong green_mask;
public ulong blue_mask;
public IntPtr obdata; /* hook for the object routines to hang on */
}
public struct XWindowAttributes
{
public int x;
public int y;
public int width;
public int height;
public int border_width;
public int depth;
public IntPtr visual;
public IntPtr root;
public int @class;
public int bit_gravity;
public int win_gravity;
public int backing_store;
public ulong backing_planes;
public ulong backing_pixel;
public bool save_under;
public IntPtr colormap;
public bool map_installed;
public int map_state;
public long all_event_masks;
public long your_event_mask;
public long do_not_propagate_mask;
public bool override_redirect;
public IntPtr screen;
}
}

View file

@ -0,0 +1,15 @@
using System.Runtime.InteropServices;
namespace Insight.Remote.Shared.Native.Linux;
public class LibXtst
{
[DllImport("libXtst")]
public static extern bool XTestQueryExtension(IntPtr display, out int event_base, out int error_base, out int major_version, out int minor_version);
[DllImport("libXtst")]
public static extern void XTestFakeKeyEvent(IntPtr display, uint keycode, bool is_press, ulong delay);
[DllImport("libXtst")]
public static extern void XTestFakeButtonEvent(IntPtr display, uint button, bool is_press, ulong delay);
[DllImport("libXtst")]
public static extern void XTestFakeMotionEvent(IntPtr display, int screen_number, int x, int y, ulong delay);
}

View file

@ -0,0 +1,9 @@
using System.Runtime.InteropServices;
namespace Insight.Remote.Shared.Native.Linux;
public class Libc
{
[DllImport("libc", SetLastError = true)]
public static extern uint geteuid();
}

View file

@ -0,0 +1,62 @@
/*
* Copyright © 2000 Compaq Computer Corporation, Inc.
* Copyright © 2002 Hewlett-Packard Company, Inc.
* Copyright © 2006 Intel Corporation
* Copyright © 2008 Red Hat, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*
* Author: Jim Gettys, HP Labs, Hewlett-Packard, Inc.
* Keith Packard, Intel Corporation
*/
using System.Runtime.InteropServices;
namespace Insight.Remote.Shared.Native.Linux;
public static class LibXrandr
{
[StructLayout(LayoutKind.Sequential)]
public struct XRRMonitorInfo
{
// Atom
public IntPtr name;
public bool primary;
public bool automatic;
public int noutput;
public int x;
public int y;
public int width;
public int height;
public int mwidth;
public int mheight;
// RROutput*
public IntPtr outputs;
}
[DllImport("libXrandr")]
public static extern IntPtr XRRGetMonitors(IntPtr display, IntPtr window, bool get_active, out int monitors);
[DllImport("libXrandr")]
public static extern void XRRFreeMonitors(IntPtr monitors);
[DllImport("libXrandr")]
public static extern IntPtr XRRAllocateMonitor(IntPtr display, int output);
}

View file

@ -0,0 +1,364 @@
using System.Runtime.InteropServices;
using System.Security;
namespace Insight.Remote.Shared.Native.Windows;
public static class ADVAPI32
{
#region Structs
public struct TOKEN_PRIVILEGES
{
public struct LUID
{
public uint LowPart;
public int HighPart;
}
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct LUID_AND_ATTRIBUTES
{
public LUID Luid;
public uint 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 int cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public int dwX;
public int dwY;
public int dwXSize;
public int dwYSize;
public int dwXCountChars;
public int dwYCountChars;
public int dwFillAttribute;
public int dwFlags;
public short wShowWindow;
public short 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 CREATE_UNICODE_ENVIRONMENT = 0x00000400;
public const int STARTF_USESHOWWINDOW = 0x00000001;
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 uint SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001;
public const uint SE_PRIVILEGE_ENABLED = 0x00000002;
public const uint SE_PRIVILEGE_REMOVED = 0x00000004;
public const uint SE_PRIVILEGE_USED_FOR_ACCESS = 0x80000000;
public const int 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,
uint bufferLengthInBytes,
ref TOKEN_PRIVILEGES previousState,
out uint 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), SuppressUnmanagedCodeSecurity]
public static extern bool OpenProcessToken(IntPtr ProcessHandle, int DesiredAccess, ref IntPtr TokenHandle);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern 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);
#endregion
}

View file

@ -0,0 +1,79 @@
using System.Runtime.InteropServices;
namespace Insight.Remote.Shared.Native.Windows;
public static class GDI32
{
#region Enums
/// <summary>
/// Specifies a raster-operation code. These codes define how the color data for the
/// source rectangle is to be combined with the color data for the destination
/// rectangle to achieve the final color.
/// </summary>
public enum TernaryRasterOperations : uint
{
/// <summary>dest = source</summary>
SRCCOPY = 0x00CC0020,
/// <summary>dest = source OR dest</summary>
SRCPAINT = 0x00EE0086,
/// <summary>dest = source AND dest</summary>
SRCAND = 0x008800C6,
/// <summary>dest = source XOR dest</summary>
SRCINVERT = 0x00660046,
/// <summary>dest = source AND (NOT dest)</summary>
SRCERASE = 0x00440328,
/// <summary>dest = (NOT source)</summary>
NOTSRCCOPY = 0x00330008,
/// <summary>dest = (NOT src) AND (NOT dest)</summary>
NOTSRCERASE = 0x001100A6,
/// <summary>dest = (source AND pattern)</summary>
MERGECOPY = 0x00C000CA,
/// <summary>dest = (NOT source) OR dest</summary>
MERGEPAINT = 0x00BB0226,
/// <summary>dest = pattern</summary>
PATCOPY = 0x00F00021,
/// <summary>dest = DPSnoo</summary>
PATPAINT = 0x00FB0A09,
/// <summary>dest = pattern XOR dest</summary>
PATINVERT = 0x005A0049,
/// <summary>dest = (NOT dest)</summary>
DSTINVERT = 0x00550009,
/// <summary>dest = BLACK</summary>
BLACKNESS = 0x00000042,
/// <summary>dest = WHITE</summary>
WHITENESS = 0x00FF0062,
/// <summary>
/// Capture window as seen on screen. This includes layered windows
/// such as WPF windows with AllowsTransparency="true"
/// </summary>
CAPTUREBLT = 0x40000000
}
#endregion
#region DLL Imports
[DllImport("gdi32.dll", EntryPoint = "BitBlt", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool BitBlt([In] IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, [In] IntPtr hdcSrc, int nXSrc, int nYSrc, TernaryRasterOperations dwRop);
[DllImport("gdi32.dll")]
public static extern IntPtr CreateDC(string lpszDriver, string lpszDevice, string lpszOutput, IntPtr lpInitData);
[DllImport("GDI32.dll")]
public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight); [DllImport("GDI32.dll")]
public static extern IntPtr CreateCompatibleDC(IntPtr hdc);
[DllImport("GDI32.dll")]
public static extern bool DeleteDC(IntPtr hdc);
[DllImport("GDI32.dll")]
public static extern bool DeleteObject(IntPtr hObject);
[DllImport("GDI32.dll")]
public static extern IntPtr GetDeviceCaps(IntPtr hdc, int nIndex);
[DllImport("GDI32.dll")]
public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
#endregion
}

View file

@ -0,0 +1,88 @@
using System.Runtime.InteropServices;
namespace Insight.Remote.Shared.Native.Windows;
public static class Kernel32
{
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool CloseHandle(IntPtr hSnapshot);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetCommandLine();
[DllImport("kernel32.dll")]
public static extern IntPtr GetConsoleWindow();
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool GlobalMemoryStatusEx([In, Out] MEMORYSTATUSEX lpBuffer);
[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId);
[DllImport("kernel32.dll")]
public static extern bool ProcessIdToSessionId(uint dwProcessId, ref uint pSessionId);
[DllImport("kernel32.dll")]
public static extern uint WTSGetActiveConsoleSessionId();
/// <summary>
/// contains information about the current state of both physical and virtual memory, including extended memory
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class MEMORYSTATUSEX
{
/// <summary>
/// Size of the structure, in bytes. You must set this member before calling GlobalMemoryStatusEx.
/// </summary>
public uint dwLength;
/// <summary>
/// Number between 0 and 100 that specifies the approximate percentage of physical memory that is in use (0 indicates no memory use and 100 indicates full memory use).
/// </summary>
public uint dwMemoryLoad;
/// <summary>
/// Total size of physical memory, in bytes.
/// </summary>
public ulong ullTotalPhys;
/// <summary>
/// Size of physical memory available, in bytes.
/// </summary>
public ulong ullAvailPhys;
/// <summary>
/// Size of the committed memory limit, in bytes. This is physical memory plus the size of the page file, minus a small overhead.
/// </summary>
public ulong ullTotalPageFile;
/// <summary>
/// Size of available memory to commit, in bytes. The limit is ullTotalPageFile.
/// </summary>
public ulong ullAvailPageFile;
/// <summary>
/// Total size of the user mode portion of the virtual address space of the calling process, in bytes.
/// </summary>
public ulong ullTotalVirtual;
/// <summary>
/// Size of unreserved and uncommitted memory in the user mode portion of the virtual address space of the calling process, in bytes.
/// </summary>
public ulong ullAvailVirtual;
/// <summary>
/// Size of unreserved and uncommitted memory in the extended portion of the virtual address space of the calling process, in bytes.
/// </summary>
public ulong ullAvailExtendedVirtual;
/// <summary>
/// Initializes a new instance of the <see cref="T:MEMORYSTATUSEX"/> class.
/// </summary>
public MEMORYSTATUSEX()
{
dwLength = (uint)Marshal.SizeOf(typeof(MEMORYSTATUSEX));
}
}
}

View file

@ -0,0 +1,376 @@
using Microsoft.Win32.SafeHandles;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
namespace Insight.Remote.Shared.Native.Windows;
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
{
readonly UInt32 PagedPoolLimit;
readonly UInt32 NonPagedPoolLimit;
readonly UInt32 MinimumWorkingSetSize;
readonly UInt32 MaximumWorkingSetSize;
readonly UInt32 PagefileLimit;
readonly 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]
protected override bool ReleaseHandle()
{
// LsaDeregisterLogonProcess returns an NTSTATUS
return LsaDeregisterLogonProcess(handle) >= 0;
}
}
[DllImport("secur32.dll", SetLastError = true)]
[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 kerbLogInfo;
SECUR32.LSA_STRING logonProc = new()
{
Buffer = Marshal.StringToHGlobalAuto("InstaLogon"),
Length = (ushort)Marshal.SizeOf(Marshal.StringToHGlobalAuto("InstaLogon")),
MaximumLength = (ushort)Marshal.SizeOf(Marshal.StringToHGlobalAuto("InstaLogon"))
};
SECUR32.LSA_STRING originName = new()
{
Buffer = Marshal.StringToHGlobalAuto("InstaLogon"),
Length = (ushort)Marshal.SizeOf(Marshal.StringToHGlobalAuto("InstaLogon")),
MaximumLength = (ushort)Marshal.SizeOf(Marshal.StringToHGlobalAuto("InstaLogon"))
};
SECUR32.LSA_STRING authPackage = new()
{
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 IntPtr pluid);
LsaConnectUntrusted(out IntPtr lsaHan);
//SECUR32.LsaRegisterLogonProcess(hLogonProc, out lsaHan, out secMode);
SECUR32.LsaLookupAuthenticationPackage(lsaHan, ref authPackage, out uint authPackID);
kerbLogInfo = Marshal.AllocHGlobal(Marshal.SizeOf(kli));
Marshal.StructureToPtr(kli, kerbLogInfo, false);
var ts = new SECUR32.TOKEN_SOURCE("Insta");
SECUR32.LsaLogonUser(
lsaHan,
ref originName,
SECUR32.SecurityLogonType.Interactive,
authPackID,
kerbLogInfo,
(uint)Marshal.SizeOf(kerbLogInfo),
IntPtr.Zero,
ref ts,
out IntPtr profBuf,
out uint profBufLen,
out long logonID,
out IntPtr logonToken,
out QUOTA_LIMITS quotas,
out WinStatusCodes subStatus);
}
}

View file

@ -0,0 +1,51 @@
using System.Runtime.InteropServices;
namespace Insight.Remote.Shared.Native.Windows;
// https://docs.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-isos
public class Shlwapi
{
[DllImport("shlwapi.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsOS(OsType osType);
}
public enum OsType
{
OS_WINDOWS = 0,
OS_NT = 1,
OS_WIN95ORGREATER = 2,
OS_NT4ORGREATER = 3,
OS_WIN98ORGREATER = 5,
OS_WIN98_GOLD = 6,
OS_WIN2000ORGREATER = 7,
OS_WIN2000PRO = 8,
OS_WIN2000SERVER = 9,
OS_WIN2000ADVSERVER = 10,
OS_WIN2000DATACENTER = 11,
OS_WIN2000TERMINAL = 12,
OS_EMBEDDED = 13,
OS_TERMINALCLIENT = 14,
OS_TERMINALREMOTEADMIN = 15,
OS_WIN95_GOLD = 16,
OS_MEORGREATER = 17,
OS_XPORGREATER = 18,
OS_HOME = 19,
OS_PROFESSIONAL = 20,
OS_DATACENTER = 21,
OS_ADVSERVER = 22,
OS_SERVER = 23,
OS_TERMINALSERVER = 24,
OS_PERSONALTERMINALSERVER = 25,
OS_FASTUSERSWITCHING = 26,
OS_WELCOMELOGONUI = 27,
OS_DOMAINMEMBER = 28,
OS_ANYSERVER = 29,
OS_WOW6432 = 30,
OS_WEBSERVER = 31,
OS_SMALLBUSINESSSERVER = 32,
OS_TABLETPC = 33,
OS_SERVERADMINUI = 34,
OS_MEDIACENTER = 35,
OS_APPLIANCE = 36,
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,78 @@
using System.Runtime.InteropServices;
namespace Insight.Remote.Shared.Native.Windows;
public static class WTSAPI32
{
public static IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero;
public enum WTS_CONNECTSTATE_CLASS
{
WTSActive,
WTSConnected,
WTSConnectQuery,
WTSShadow,
WTSDisconnected,
WTSIdle,
WTSListen,
WTSReset,
WTSDown,
WTSInit
}
public enum WTS_INFO_CLASS
{
WTSInitialProgram,
WTSApplicationName,
WTSWorkingDirectory,
WTSOEMId,
WTSSessionId,
WTSUserName,
WTSWinStationName,
WTSDomainName,
WTSConnectState,
WTSClientBuildNumber,
WTSClientName,
WTSClientDirectory,
WTSClientProductId,
WTSClientHardwareId,
WTSClientAddress,
WTSClientDisplay,
WTSClientProtocolType,
WTSIdleTime,
WTSLogonTime,
WTSIncomingBytes,
WTSOutgoingBytes,
WTSIncomingFrames,
WTSOutgoingFrames,
WTSClientInfo,
WTSSessionInfo
}
[DllImport("wtsapi32.dll", SetLastError = true)]
public static extern int WTSEnumerateSessions(
IntPtr hServer,
int Reserved,
int Version,
ref IntPtr ppSessionInfo,
ref int pCount);
[DllImport("wtsapi32.dll", ExactSpelling = true, SetLastError = false)]
public static extern void WTSFreeMemory(IntPtr memory);
[DllImport("Wtsapi32.dll")]
public static extern bool WTSQuerySessionInformation(IntPtr hServer, uint sessionId, WTS_INFO_CLASS wtsInfoClass, out IntPtr ppBuffer, out uint pBytesReturned);
[DllImport("wtsapi32.dll", SetLastError = true)]
static extern IntPtr WTSOpenServer(string pServerName);
[StructLayout(LayoutKind.Sequential)]
public struct WTS_SESSION_INFO
{
public uint SessionID;
[MarshalAs(UnmanagedType.LPStr)]
public string pWinStationName;
public WTS_CONNECTSTATE_CLASS State;
}
}

View file

@ -0,0 +1,285 @@
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Text;
using static Insight.Remote.Shared.Native.Windows.ADVAPI32;
using static Insight.Remote.Shared.Native.Windows.User32;
namespace Insight.Remote.Shared.Native.Windows;
// TODO: Use https://github.com/dotnet/pinvoke for all p/invokes. Remove signatures from this project.
public class Win32Interop
{
private static IntPtr _lastInputDesktop;
public static List<WindowsSessionDto> GetActiveSessions()
{
var sessions = new List<WindowsSessionDto>();
var consoleSessionId = Kernel32.WTSGetActiveConsoleSessionId();
sessions.Add(new WindowsSessionDto()
{
Id = consoleSessionId,
Type = WindowsSessionType.Console,
Name = "Console",
Username = GetUsernameFromSessionId(consoleSessionId)
});
IntPtr ppSessionInfo = IntPtr.Zero;
var count = 0;
var enumSessionResult = WTSAPI32.WTSEnumerateSessions(WTSAPI32.WTS_CURRENT_SERVER_HANDLE, 0, 1, ref ppSessionInfo, ref count);
var dataSize = Marshal.SizeOf(typeof(WTSAPI32.WTS_SESSION_INFO));
var current = ppSessionInfo;
if (enumSessionResult != 0)
{
for (int i = 0; i < count; i++)
{
var wtsInfo = Marshal.PtrToStructure(current, typeof(WTSAPI32.WTS_SESSION_INFO));
if (wtsInfo is null)
{
continue;
}
var sessionInfo = (WTSAPI32.WTS_SESSION_INFO)wtsInfo;
current += dataSize;
if (sessionInfo.State == WTSAPI32.WTS_CONNECTSTATE_CLASS.WTSActive && sessionInfo.SessionID != consoleSessionId)
{
sessions.Add(new WindowsSessionDto()
{
Id = sessionInfo.SessionID,
Name = sessionInfo.pWinStationName,
Type = WindowsSessionType.RDP,
Username = GetUsernameFromSessionId(sessionInfo.SessionID)
});
}
}
}
return sessions;
}
public static string GetCommandLine()
{
var commandLinePtr = Kernel32.GetCommandLine();
return Marshal.PtrToStringAuto(commandLinePtr) ?? string.Empty;
}
public static bool GetCurrentDesktop(out string desktopName)
{
var inputDesktop = OpenInputDesktop();
try
{
byte[] deskBytes = new byte[256];
if (!GetUserObjectInformationW(inputDesktop, UOI_NAME, deskBytes, 256, out uint lenNeeded))
{
desktopName = string.Empty;
return false;
}
desktopName = Encoding.Unicode.GetString(deskBytes.Take((int)lenNeeded).ToArray()).Replace("\0", "");
return true;
}
finally
{
CloseDesktop(inputDesktop);
}
}
public static string GetUsernameFromSessionId(uint sessionId)
{
var username = string.Empty;
if (WTSAPI32.WTSQuerySessionInformation(IntPtr.Zero, sessionId, WTSAPI32.WTS_INFO_CLASS.WTSUserName, out var buffer, out var strLen) && strLen > 1)
{
username = Marshal.PtrToStringAnsi(buffer);
WTSAPI32.WTSFreeMemory(buffer);
}
return username ?? string.Empty;
}
public static IntPtr OpenInputDesktop()
{
return User32.OpenInputDesktop(0, true, ACCESS_MASK.GENERIC_ALL);
}
public static bool CreateInteractiveSystemProcess(
string commandLine,
int targetSessionId,
bool forceConsoleSession,
string desktopName,
bool hiddenWindow,
out PROCESS_INFORMATION procInfo)
{
uint winlogonPid = 0;
var hUserTokenDup = IntPtr.Zero;
var hPToken = IntPtr.Zero;
var hProcess = IntPtr.Zero;
procInfo = new PROCESS_INFORMATION();
// If not force console, find target session. If not present,
// use last active session.
var dwSessionId = Kernel32.WTSGetActiveConsoleSessionId();
if (!forceConsoleSession)
{
var activeSessions = GetActiveSessions();
if (activeSessions.Any(x => x.Id == targetSessionId))
{
dwSessionId = (uint)targetSessionId;
}
else
{
dwSessionId = activeSessions.Last().Id;
}
}
// Obtain the process ID of the winlogon process that is running within the currently active session.
var 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.
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, 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.
var 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_UNICODE_ENVIRONMENT | CREATE_NO_WINDOW;
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = 0;
}
else
{
dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE;
}
// Create a new process in the current user's logon session.
var result = CreateProcessAsUser(
hUserTokenDup,
null,
commandLine,
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 void SetMonitorState(MonitorState state)
{
SendMessage(0xFFFF, 0x112, 0xF170, (int)state);
}
public static MessageBoxResult ShowMessageBox(IntPtr owner,
string message,
string caption,
MessageBoxType messageBoxType)
{
return (MessageBoxResult)MessageBox(owner, message, caption, (long)messageBoxType);
}
public static bool SwitchToInputDesktop()
{
try
{
CloseDesktop(_lastInputDesktop);
var inputDesktop = OpenInputDesktop();
if (inputDesktop == IntPtr.Zero)
{
return false;
}
var result = SetThreadDesktop(inputDesktop) && SwitchDesktop(inputDesktop);
_lastInputDesktop = inputDesktop;
return result;
}
catch
{
return false;
}
}
public static void SetConsoleWindowVisibility(bool isVisible)
{
var handle = Kernel32.GetConsoleWindow();
if (isVisible)
{
ShowWindow(handle, (int)SW.SW_SHOW);
}
else
{
ShowWindow(handle, (int)SW.SW_HIDE);
}
Kernel32.CloseHandle(handle);
}
[DataContract]
public class WindowsSessionDto
{
[DataMember(Name = "ID")]
public uint Id { get; set; }
[DataMember(Name = "Name")]
public string Name { get; set; } = string.Empty;
[DataMember(Name = "Type")]
public WindowsSessionType Type { get; set; }
[DataMember(Name = "Username")]
public string Username { get; set; } = string.Empty;
}
[DataContract]
public enum WindowsSessionType
{
Console = 1,
RDP = 2
}
}