using System; using System.Runtime.InteropServices; using System.Security; namespace Remotely.Desktop.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 nint lpSecurityDescriptor; public bool bInheritHandle; } [StructLayout(LayoutKind.Sequential)] public struct PROCESS_INFORMATION { public nint hProcess; public nint 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 nint lpReserved2; public nint hStdInput; public nint hStdOutput; public nint hStdError; } #endregion #region Enums public enum TOKEN_INFORMATION_CLASS { ///     /// The buffer receives a TOKEN_USER structure that contains the user account of the token.     /// TokenUser = 1, ///     /// The buffer receives a TOKEN_GROUPS structure that contains the group accounts associated with the token.     /// TokenGroups, ///     /// The buffer receives a TOKEN_PRIVILEGES structure that contains the privileges of the token.     /// TokenPrivileges, ///     /// The buffer receives a TOKEN_OWNER structure that contains the default owner security identifier (SID) for newly created objects.     /// TokenOwner, ///     /// The buffer receives a TOKEN_PRIMARY_GROUP structure that contains the default primary group SID for newly created objects.     /// TokenPrimaryGroup, ///     /// The buffer receives a TOKEN_DEFAULT_DACL structure that contains the default DACL for newly created objects.     /// TokenDefaultDacl, ///     /// The buffer receives a TOKEN_SOURCE structure that contains the source of the token. TOKEN_QUERY_SOURCE access is needed to retrieve this information.     /// TokenSource, ///     /// The buffer receives a TOKEN_TYPE value that indicates whether the token is a primary or impersonation token.     /// TokenType, ///     /// 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.     /// TokenImpersonationLevel, ///     /// The buffer receives a TOKEN_STATISTICS structure that contains various token statistics.     /// TokenStatistics, ///     /// The buffer receives a TOKEN_GROUPS structure that contains the list of restricting SIDs in a restricted token.     /// TokenRestrictedSids, ///     /// The buffer receives a DWORD value that indicates the Terminal Services session identifier that is associated with the token.     /// TokenSessionId, ///     /// 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.     /// TokenGroupsAndPrivileges, ///     /// Reserved.     /// TokenSessionReference, ///     /// The buffer receives a DWORD value that is nonzero if the token includes the SANDBOX_INERT flag.     /// TokenSandBoxInert, ///     /// Reserved.     /// TokenAuditPolicy, ///     /// The buffer receives a TOKEN_ORIGIN value.     /// TokenOrigin, ///     /// The buffer receives a TOKEN_ELEVATION_TYPE value that specifies the elevation level of the token.     /// TokenElevationType, ///     /// The buffer receives a TOKEN_LINKED_TOKEN structure that contains a handle to another token that is linked to this token.     /// TokenLinkedToken, ///     /// The buffer receives a TOKEN_ELEVATION structure that specifies whether the token is elevated.     /// TokenElevation, ///     /// The buffer receives a DWORD value that is nonzero if the token has ever been filtered.     /// TokenHasRestrictions, ///     /// The buffer receives a TOKEN_ACCESS_INFORMATION structure that specifies security information contained in the token.     /// TokenAccessInformation, ///     /// The buffer receives a DWORD value that is nonzero if virtualization is allowed for the token.     /// TokenVirtualizationAllowed, ///     /// The buffer receives a DWORD value that is nonzero if virtualization is enabled for the token.     /// TokenVirtualizationEnabled, ///     /// The buffer receives a TOKEN_MANDATORY_LABEL structure that specifies the token's integrity level.     /// TokenIntegrityLevel, ///     /// The buffer receives a DWORD value that is nonzero if the token has the UIAccess flag set.     /// TokenUIAccess, ///     /// The buffer receives a TOKEN_MANDATORY_POLICY structure that specifies the token's mandatory integrity policy.     /// TokenMandatoryPolicy, ///     /// The buffer receives the token's logon security identifier (SID).     /// TokenLogonSid, ///     /// The maximum value for this enumeration     /// 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(nint 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( nint hToken, string? lpApplicationName, string lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes, ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, nint lpEnvironment, string? lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation); [DllImport("advapi32.dll", SetLastError = true)] public static extern bool AllocateLocallyUniqueId(out nint 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( nint TokenHandle, SECUR32.TOKEN_INFORMATION_CLASS TokenInformationClass, nint 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 nint phToken); [DllImport("advapi32", SetLastError = true), SuppressUnmanagedCodeSecurity] public static extern bool OpenProcessToken(nint ProcessHandle, int DesiredAccess, ref nint TokenHandle); [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern bool DuplicateTokenEx( nint hExistingToken, uint dwDesiredAccess, ref SECURITY_ATTRIBUTES lpTokenAttributes, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, TOKEN_TYPE TokenType, out nint phNewToken); [DllImport("advapi32.dll", SetLastError = false)] public static extern uint LsaNtStatusToWinError(uint status); #endregion }