From 47c1e67f3859048fb0b038e76db774af294d2955 Mon Sep 17 00:00:00 2001 From: Alex Macocian Date: Mon, 15 Jul 2019 10:36:50 +0300 Subject: [PATCH] Implemented basic application functionality and security. --- .../Security/ProcessInformation.cs | 799 ++++++++++++++++++ SystemExtensions/SystemExtensions.csproj | 1 + 2 files changed, 800 insertions(+) create mode 100644 SystemExtensions/Security/ProcessInformation.cs diff --git a/SystemExtensions/Security/ProcessInformation.cs b/SystemExtensions/Security/ProcessInformation.cs new file mode 100644 index 0000000..081e973 --- /dev/null +++ b/SystemExtensions/Security/ProcessInformation.cs @@ -0,0 +1,799 @@ +using Microsoft.Win32.SafeHandles; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Security.Principal; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using static System.Net.Mime.MediaTypeNames; + +namespace SystemExtensions.Security +{ + /// + /// Helper class to obtain admin privileges and elevation status. + /// + /// Source code provided on https://code.msdn.microsoft.com/windowsapps/CSUACSelfElevation-644673d3 + public static class ProcessInformation + { + /// + /// The function checks whether the primary access token of the process belongs + /// to user account that is a member of the local Administrators group, even if + /// it currently is not elevated. + /// + /// + /// Returns true if the primary access token of the process belongs to user + /// account that is a member of the local Administrators group. Returns false + /// if the token does not. + /// + /// + /// When any native Windows API call fails, the function throws a Win32Exception + /// with the last error code. + /// + public static bool IsUserInAdminGroup() + { + bool fInAdminGroup = false; + SafeTokenHandle hToken = null; + SafeTokenHandle hTokenToCheck = null; + IntPtr pElevationType = IntPtr.Zero; + IntPtr pLinkedToken = IntPtr.Zero; + int cbSize = 0; + + try + { + // Open the access token of the current process for query and duplicate. + if (!NativeMethods.OpenProcessToken(Process.GetCurrentProcess().Handle, + NativeMethods.TOKEN_QUERY | NativeMethods.TOKEN_DUPLICATE, out hToken)) + { + throw new Win32Exception(); + } + + // Determine whether system is running Windows Vista or later operating + // systems (major version >= 6) because they support linked tokens, but + // previous versions (major version < 6) do not. + if (Environment.OSVersion.Version.Major >= 6) + { + // Running Windows Vista or later (major version >= 6). + // Determine token type: limited, elevated, or default. + + // Allocate a buffer for the elevation type information. + cbSize = sizeof(TOKEN_ELEVATION_TYPE); + pElevationType = Marshal.AllocHGlobal(cbSize); + if (pElevationType == IntPtr.Zero) + { + throw new Win32Exception(); + } + + // Retrieve token elevation type information. + if (!NativeMethods.GetTokenInformation(hToken, + TOKEN_INFORMATION_CLASS.TokenElevationType, pElevationType, + cbSize, out cbSize)) + { + throw new Win32Exception(); + } + + // Marshal the TOKEN_ELEVATION_TYPE enum from native to .NET. + TOKEN_ELEVATION_TYPE elevType = (TOKEN_ELEVATION_TYPE) + Marshal.ReadInt32(pElevationType); + + // If limited, get the linked elevated token for further check. + if (elevType == TOKEN_ELEVATION_TYPE.TokenElevationTypeLimited) + { + // Allocate a buffer for the linked token. + cbSize = IntPtr.Size; + pLinkedToken = Marshal.AllocHGlobal(cbSize); + if (pLinkedToken == IntPtr.Zero) + { + throw new Win32Exception(); + } + + // Get the linked token. + if (!NativeMethods.GetTokenInformation(hToken, + TOKEN_INFORMATION_CLASS.TokenLinkedToken, pLinkedToken, + cbSize, out cbSize)) + { + throw new Win32Exception(); + } + + // Marshal the linked token value from native to .NET. + IntPtr hLinkedToken = Marshal.ReadIntPtr(pLinkedToken); + hTokenToCheck = new SafeTokenHandle(hLinkedToken); + } + } + + // CheckTokenMembership requires an impersonation token. If we just got + // a linked token, it already is an impersonation token. If we did not + // get a linked token, duplicate the original into an impersonation + // token for CheckTokenMembership. + if (hTokenToCheck == null) + { + if (!NativeMethods.DuplicateToken(hToken, + SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, + out hTokenToCheck)) + { + throw new Win32Exception(); + } + } + + // Check if the token to be checked contains admin SID. + WindowsIdentity id = new WindowsIdentity(hTokenToCheck.DangerousGetHandle()); + WindowsPrincipal principal = new WindowsPrincipal(id); + fInAdminGroup = principal.IsInRole(WindowsBuiltInRole.Administrator); + } + finally + { + // Centralized cleanup for all allocated resources. + if (hToken != null) + { + hToken.Close(); + hToken = null; + } + if (hTokenToCheck != null) + { + hTokenToCheck.Close(); + hTokenToCheck = null; + } + if (pElevationType != IntPtr.Zero) + { + Marshal.FreeHGlobal(pElevationType); + pElevationType = IntPtr.Zero; + } + if (pLinkedToken != IntPtr.Zero) + { + Marshal.FreeHGlobal(pLinkedToken); + pLinkedToken = IntPtr.Zero; + } + } + + return fInAdminGroup; + } + + + /// + /// The function checks whether the current process is run as administrator. + /// In other words, it dictates whether the primary access token of the + /// process belongs to user account that is a member of the local + /// Administrators group and it is elevated. + /// + /// + /// Returns true if the primary access token of the process belongs to user + /// account that is a member of the local Administrators group and it is + /// elevated. Returns false if the token does not. + /// + public static bool IsRunAsAdmin() + { + WindowsIdentity id = WindowsIdentity.GetCurrent(); + WindowsPrincipal principal = new WindowsPrincipal(id); + return principal.IsInRole(WindowsBuiltInRole.Administrator); + } + + + /// + /// The function gets the elevation information of the current process. It + /// dictates whether the process is elevated or not. Token elevation is only + /// available on Windows Vista and newer operating systems, thus + /// IsProcessElevated throws a C++ exception if it is called on systems prior + /// to Windows Vista. It is not appropriate to use this function to determine + /// whether a process is run as administartor. + /// + /// + /// Returns true if the process is elevated. Returns false if it is not. + /// + /// + /// When any native Windows API call fails, the function throws a Win32Exception + /// with the last error code. + /// + /// + /// TOKEN_INFORMATION_CLASS provides TokenElevationType to check the elevation + /// type (TokenElevationTypeDefault / TokenElevationTypeLimited / + /// TokenElevationTypeFull) of the process. It is different from TokenElevation + /// in that, when UAC is turned off, elevation type always returns + /// TokenElevationTypeDefault even though the process is elevated (Integrity + /// Level == High). In other words, it is not safe to say if the process is + /// elevated based on elevation type. Instead, we should use TokenElevation. + /// + public static bool IsProcessElevated() + { + bool fIsElevated = false; + SafeTokenHandle hToken = null; + int cbTokenElevation = 0; + IntPtr pTokenElevation = IntPtr.Zero; + + try + { + // Open the access token of the current process with TOKEN_QUERY. + if (!NativeMethods.OpenProcessToken(Process.GetCurrentProcess().Handle, + NativeMethods.TOKEN_QUERY, out hToken)) + { + throw new Win32Exception(); + } + + // Allocate a buffer for the elevation information. + cbTokenElevation = Marshal.SizeOf(typeof(TOKEN_ELEVATION)); + pTokenElevation = Marshal.AllocHGlobal(cbTokenElevation); + if (pTokenElevation == IntPtr.Zero) + { + throw new Win32Exception(); + } + + // Retrieve token elevation information. + if (!NativeMethods.GetTokenInformation(hToken, + TOKEN_INFORMATION_CLASS.TokenElevation, pTokenElevation, + cbTokenElevation, out cbTokenElevation)) + { + // When the process is run on operating systems prior to Windows + // Vista, GetTokenInformation returns false with the error code + // ERROR_INVALID_PARAMETER because TokenElevation is not supported + // on those operating systems. + throw new Win32Exception(); + } + + // Marshal the TOKEN_ELEVATION struct from native to .NET object. + TOKEN_ELEVATION elevation = (TOKEN_ELEVATION)Marshal.PtrToStructure( + pTokenElevation, typeof(TOKEN_ELEVATION)); + + // TOKEN_ELEVATION.TokenIsElevated is a non-zero value if the token + // has elevated privileges; otherwise, a zero value. + fIsElevated = (elevation.TokenIsElevated != 0); + } + finally + { + // Centralized cleanup for all allocated resources. + if (hToken != null) + { + hToken.Close(); + hToken = null; + } + if (pTokenElevation != IntPtr.Zero) + { + Marshal.FreeHGlobal(pTokenElevation); + pTokenElevation = IntPtr.Zero; + cbTokenElevation = 0; + } + } + + return fIsElevated; + } + + + /// + /// The function gets the integrity level of the current process. Integrity + /// level is only available on Windows Vista and newer operating systems, thus + /// GetProcessIntegrityLevel throws a C++ exception if it is called on systems + /// prior to Windows Vista. + /// + /// + /// Returns the integrity level of the current process. It is usually one of + /// these values: + /// + /// SECURITY_MANDATORY_UNTRUSTED_RID - means untrusted level. It is used + /// by processes started by the Anonymous group. Blocks most write access. + /// (SID: S-1-16-0x0) + /// + /// SECURITY_MANDATORY_LOW_RID - means low integrity level. It is used by + /// Protected Mode Internet Explorer. Blocks write acess to most objects + /// (such as files and registry keys) on the system. (SID: S-1-16-0x1000) + /// + /// SECURITY_MANDATORY_MEDIUM_RID - means medium integrity level. It is + /// used by normal applications being launched while UAC is enabled. + /// (SID: S-1-16-0x2000) + /// + /// SECURITY_MANDATORY_HIGH_RID - means high integrity level. It is used + /// by administrative applications launched through elevation when UAC is + /// enabled, or normal applications if UAC is disabled and the user is an + /// administrator. (SID: S-1-16-0x3000) + /// + /// SECURITY_MANDATORY_SYSTEM_RID - means system integrity level. It is + /// used by services and other system-level applications (such as Wininit, + /// Winlogon, Smss, etc.) (SID: S-1-16-0x4000) + /// + /// + /// + /// When any native Windows API call fails, the function throws a Win32Exception + /// with the last error code. + /// + public static int GetProcessIntegrityLevel() + { + int IL = -1; + SafeTokenHandle hToken = null; + int cbTokenIL = 0; + IntPtr pTokenIL = IntPtr.Zero; + + try + { + // Open the access token of the current process with TOKEN_QUERY. + if (!NativeMethods.OpenProcessToken(Process.GetCurrentProcess().Handle, + NativeMethods.TOKEN_QUERY, out hToken)) + { + throw new Win32Exception(); + } + + // Then we must query the size of the integrity level information + // associated with the token. Note that we expect GetTokenInformation + // to return false with the ERROR_INSUFFICIENT_BUFFER error code + // because we've given it a null buffer. On exit cbTokenIL will tell + // the size of the group information. + if (!NativeMethods.GetTokenInformation(hToken, + TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, IntPtr.Zero, 0, + out cbTokenIL)) + { + int error = Marshal.GetLastWin32Error(); + if (error != NativeMethods.ERROR_INSUFFICIENT_BUFFER) + { + // When the process is run on operating systems prior to + // Windows Vista, GetTokenInformation returns false with the + // ERROR_INVALID_PARAMETER error code because + // TokenIntegrityLevel is not supported on those OS's. + throw new Win32Exception(error); + } + } + + // Now we allocate a buffer for the integrity level information. + pTokenIL = Marshal.AllocHGlobal(cbTokenIL); + if (pTokenIL == IntPtr.Zero) + { + throw new Win32Exception(); + } + + // Now we ask for the integrity level information again. This may fail + // if an administrator has added this account to an additional group + // between our first call to GetTokenInformation and this one. + if (!NativeMethods.GetTokenInformation(hToken, + TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, pTokenIL, cbTokenIL, + out cbTokenIL)) + { + throw new Win32Exception(); + } + + // Marshal the TOKEN_MANDATORY_LABEL struct from native to .NET object. + TOKEN_MANDATORY_LABEL tokenIL = (TOKEN_MANDATORY_LABEL) + Marshal.PtrToStructure(pTokenIL, typeof(TOKEN_MANDATORY_LABEL)); + + // Integrity Level SIDs are in the form of S-1-16-0xXXXX. (e.g. + // S-1-16-0x1000 stands for low integrity level SID). There is one + // and only one subauthority. + IntPtr pIL = NativeMethods.GetSidSubAuthority(tokenIL.Label.Sid, 0); + IL = Marshal.ReadInt32(pIL); + } + finally + { + // Centralized cleanup for all allocated resources. + if (hToken != null) + { + hToken.Close(); + hToken = null; + } + if (pTokenIL != IntPtr.Zero) + { + Marshal.FreeHGlobal(pTokenIL); + pTokenIL = IntPtr.Zero; + cbTokenIL = 0; + } + } + + return IL; + } + + /// + /// Elevate process to administration rights. + /// + /// True if the elevation succeeded or false if it failed. + public static bool ElevateProcess() + { + if (!IsRunAsAdmin()) + { + // Launch itself as administrator + ProcessStartInfo proc = new ProcessStartInfo(); + proc.UseShellExecute = true; + proc.WorkingDirectory = Environment.CurrentDirectory; + proc.FileName = GetApplicationPath() + Assembly.GetCallingAssembly().GetName().FullName; + proc.Verb = "runas"; + + + try + { + Process.Start(proc); + Process.GetCurrentProcess().Close(); // Quit itself + return true; + } + catch + { + // The user refused the elevation. + // Do nothing and return directly ... + return false; + } + } + else + { + return true; + } + } + + /// + /// Gets the application path of the running assembly. + /// + /// String containing the path to the executing assembly. + public static string GetApplicationPath() + { + var exePath = Path.GetDirectoryName(System.Reflection + .Assembly.GetExecutingAssembly().CodeBase); + Regex appPathMatcher = new Regex(@"(? + /// The TOKEN_INFORMATION_CLASS enumeration type contains values that + /// specify the type of information being assigned to or retrieved from + /// an access token. + /// + internal enum TOKEN_INFORMATION_CLASS + { + TokenUser = 1, + TokenGroups, + TokenPrivileges, + TokenOwner, + TokenPrimaryGroup, + TokenDefaultDacl, + TokenSource, + TokenType, + TokenImpersonationLevel, + TokenStatistics, + TokenRestrictedSids, + TokenSessionId, + TokenGroupsAndPrivileges, + TokenSessionReference, + TokenSandBoxInert, + TokenAuditPolicy, + TokenOrigin, + TokenElevationType, + TokenLinkedToken, + TokenElevation, + TokenHasRestrictions, + TokenAccessInformation, + TokenVirtualizationAllowed, + TokenVirtualizationEnabled, + TokenIntegrityLevel, + TokenUIAccess, + TokenMandatoryPolicy, + TokenLogonSid, + MaxTokenInfoClass + } + + /// + /// The WELL_KNOWN_SID_TYPE enumeration type is a list of commonly used + /// security identifiers (SIDs). Programs can pass these values to the + /// CreateWellKnownSid function to create a SID from this list. + /// + internal enum WELL_KNOWN_SID_TYPE + { + WinNullSid = 0, + WinWorldSid = 1, + WinLocalSid = 2, + WinCreatorOwnerSid = 3, + WinCreatorGroupSid = 4, + WinCreatorOwnerServerSid = 5, + WinCreatorGroupServerSid = 6, + WinNtAuthoritySid = 7, + WinDialupSid = 8, + WinNetworkSid = 9, + WinBatchSid = 10, + WinInteractiveSid = 11, + WinServiceSid = 12, + WinAnonymousSid = 13, + WinProxySid = 14, + WinEnterpriseControllersSid = 15, + WinSelfSid = 16, + WinAuthenticatedUserSid = 17, + WinRestrictedCodeSid = 18, + WinTerminalServerSid = 19, + WinRemoteLogonIdSid = 20, + WinLogonIdsSid = 21, + WinLocalSystemSid = 22, + WinLocalServiceSid = 23, + WinNetworkServiceSid = 24, + WinBuiltinDomainSid = 25, + WinBuiltinAdministratorsSid = 26, + WinBuiltinUsersSid = 27, + WinBuiltinGuestsSid = 28, + WinBuiltinPowerUsersSid = 29, + WinBuiltinAccountOperatorsSid = 30, + WinBuiltinSystemOperatorsSid = 31, + WinBuiltinPrintOperatorsSid = 32, + WinBuiltinBackupOperatorsSid = 33, + WinBuiltinReplicatorSid = 34, + WinBuiltinPreWindows2000CompatibleAccessSid = 35, + WinBuiltinRemoteDesktopUsersSid = 36, + WinBuiltinNetworkConfigurationOperatorsSid = 37, + WinAccountAdministratorSid = 38, + WinAccountGuestSid = 39, + WinAccountKrbtgtSid = 40, + WinAccountDomainAdminsSid = 41, + WinAccountDomainUsersSid = 42, + WinAccountDomainGuestsSid = 43, + WinAccountComputersSid = 44, + WinAccountControllersSid = 45, + WinAccountCertAdminsSid = 46, + WinAccountSchemaAdminsSid = 47, + WinAccountEnterpriseAdminsSid = 48, + WinAccountPolicyAdminsSid = 49, + WinAccountRasAndIasServersSid = 50, + WinNTLMAuthenticationSid = 51, + WinDigestAuthenticationSid = 52, + WinSChannelAuthenticationSid = 53, + WinThisOrganizationSid = 54, + WinOtherOrganizationSid = 55, + WinBuiltinIncomingForestTrustBuildersSid = 56, + WinBuiltinPerfMonitoringUsersSid = 57, + WinBuiltinPerfLoggingUsersSid = 58, + WinBuiltinAuthorizationAccessSid = 59, + WinBuiltinTerminalServerLicenseServersSid = 60, + WinBuiltinDCOMUsersSid = 61, + WinBuiltinIUsersSid = 62, + WinIUserSid = 63, + WinBuiltinCryptoOperatorsSid = 64, + WinUntrustedLabelSid = 65, + WinLowLabelSid = 66, + WinMediumLabelSid = 67, + WinHighLabelSid = 68, + WinSystemLabelSid = 69, + WinWriteRestrictedCodeSid = 70, + WinCreatorOwnerRightsSid = 71, + WinCacheablePrincipalsGroupSid = 72, + WinNonCacheablePrincipalsGroupSid = 73, + WinEnterpriseReadonlyControllersSid = 74, + WinAccountReadonlyControllersSid = 75, + WinBuiltinEventLogReadersGroup = 76, + WinNewEnterpriseReadonlyControllersSid = 77, + WinBuiltinCertSvcDComAccessGroup = 78 + } + + /// + /// The SECURITY_IMPERSONATION_LEVEL enumeration type contains values + /// that specify security impersonation levels. Security impersonation + /// levels govern the degree to which a server process can act on behalf + /// of a client process. + /// + internal enum SECURITY_IMPERSONATION_LEVEL + { + SecurityAnonymous, + SecurityIdentification, + SecurityImpersonation, + SecurityDelegation + } + + /// + /// The TOKEN_ELEVATION_TYPE enumeration indicates the elevation type of + /// token being queried by the GetTokenInformation function or set by + /// the SetTokenInformation function. + /// + internal enum TOKEN_ELEVATION_TYPE + { + TokenElevationTypeDefault = 1, + TokenElevationTypeFull, + TokenElevationTypeLimited + } + + /// + /// The structure represents a security identifier (SID) and its + /// attributes. SIDs are used to uniquely identify users or groups. + /// + [StructLayout(LayoutKind.Sequential)] + internal struct SID_AND_ATTRIBUTES + { + public IntPtr Sid; + public UInt32 Attributes; + } + + /// + /// The structure indicates whether a token has elevated privileges. + /// + [StructLayout(LayoutKind.Sequential)] + internal struct TOKEN_ELEVATION + { + public Int32 TokenIsElevated; + } + + /// + /// The structure specifies the mandatory integrity level for a token. + /// + [StructLayout(LayoutKind.Sequential)] + internal struct TOKEN_MANDATORY_LABEL + { + public SID_AND_ATTRIBUTES Label; + } + + /// + /// Represents a wrapper class for a token handle. + /// + internal class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid + { + private SafeTokenHandle() : base(true) + { + } + + internal SafeTokenHandle(IntPtr handle) : base(true) + { + base.SetHandle(handle); + } + + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + internal static extern bool CloseHandle(IntPtr handle); + + protected override bool ReleaseHandle() + { + return CloseHandle(base.handle); + } + } + + internal class NativeMethods + { + // Token Specific Access Rights + + public const UInt32 STANDARD_RIGHTS_REQUIRED = 0x000F0000; + public const UInt32 STANDARD_RIGHTS_READ = 0x00020000; + public const UInt32 TOKEN_ASSIGN_PRIMARY = 0x0001; + public const UInt32 TOKEN_DUPLICATE = 0x0002; + public const UInt32 TOKEN_IMPERSONATE = 0x0004; + public const UInt32 TOKEN_QUERY = 0x0008; + public const UInt32 TOKEN_QUERY_SOURCE = 0x0010; + public const UInt32 TOKEN_ADJUST_PRIVILEGES = 0x0020; + public const UInt32 TOKEN_ADJUST_GROUPS = 0x0040; + public const UInt32 TOKEN_ADJUST_DEFAULT = 0x0080; + public const UInt32 TOKEN_ADJUST_SESSIONID = 0x0100; + public const UInt32 TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY); + public const UInt32 TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | + TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE | + TOKEN_QUERY | TOKEN_QUERY_SOURCE | TOKEN_ADJUST_PRIVILEGES | + TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID); + + + public const Int32 ERROR_INSUFFICIENT_BUFFER = 122; + + + // Integrity Levels + + public const Int32 SECURITY_MANDATORY_UNTRUSTED_RID = 0x00000000; + public const Int32 SECURITY_MANDATORY_LOW_RID = 0x00001000; + public const Int32 SECURITY_MANDATORY_MEDIUM_RID = 0x00002000; + public const Int32 SECURITY_MANDATORY_HIGH_RID = 0x00003000; + public const Int32 SECURITY_MANDATORY_SYSTEM_RID = 0x00004000; + + + /// + /// The function opens the access token associated with a process. + /// + /// + /// A handle to the process whose access token is opened. + /// + /// + /// Specifies an access mask that specifies the requested types of + /// access to the access token. + /// + /// + /// Outputs a handle that identifies the newly opened access token + /// when the function returns. + /// + /// + [DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool OpenProcessToken(IntPtr hProcess, + UInt32 desiredAccess, out SafeTokenHandle hToken); + + + /// + /// The function creates a new access token that duplicates one + /// already in existence. + /// + /// + /// A handle to an access token opened with TOKEN_DUPLICATE access. + /// + /// + /// Specifies a SECURITY_IMPERSONATION_LEVEL enumerated type that + /// supplies the impersonation level of the new token. + /// + /// + /// Outputs a handle to the duplicate token. + /// + /// + [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public extern static bool DuplicateToken( + SafeTokenHandle ExistingTokenHandle, + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, + out SafeTokenHandle DuplicateTokenHandle); + + + /// + /// The function retrieves a specified type of information about an + /// access token. The calling process must have appropriate access + /// rights to obtain the information. + /// + /// + /// A handle to an access token from which information is retrieved. + /// + /// + /// Specifies a value from the TOKEN_INFORMATION_CLASS enumerated + /// type to identify the type of information the function retrieves. + /// + /// + /// A pointer to a buffer the function fills with the requested + /// information. + /// + /// + /// Specifies the size, in bytes, of the buffer pointed to by the + /// TokenInformation parameter. + /// + /// + /// A pointer to a variable that receives the number of bytes needed + /// for the buffer pointed to by the TokenInformation parameter. + /// + /// + [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool GetTokenInformation( + SafeTokenHandle hToken, + TOKEN_INFORMATION_CLASS tokenInfoClass, + IntPtr pTokenInfo, + Int32 tokenInfoLength, + out Int32 returnLength); + + + /// + /// Sets the elevation required state for a specified button or + /// command link to display an elevated icon. + /// + public const UInt32 BCM_SETSHIELD = 0x160C; + + + /// + /// Sends the specified message to a window or windows. The function + /// calls the window procedure for the specified window and does not + /// return until the window procedure has processed the message. + /// + /// + /// Handle to the window whose window procedure will receive the + /// message. + /// + /// Specifies the message to be sent. + /// + /// Specifies additional message-specific information. + /// + /// + /// Specifies additional message-specific information. + /// + /// + [DllImport("user32", CharSet = CharSet.Auto, SetLastError = true)] + public static extern int SendMessage(IntPtr hWnd, UInt32 Msg, int wParam, IntPtr lParam); + + + /// + /// The function returns a pointer to a specified subauthority in a + /// security identifier (SID). The subauthority value is a relative + /// identifier (RID). + /// + /// + /// A pointer to the SID structure from which a pointer to a + /// subauthority is to be returned. + /// + /// + /// Specifies an index value identifying the subauthority array + /// element whose address the function will return. + /// + /// + /// If the function succeeds, the return value is a pointer to the + /// specified SID subauthority. To get extended error information, + /// call GetLastError. If the function fails, the return value is + /// undefined. The function fails if the specified SID structure is + /// not valid or if the index value specified by the nSubAuthority + /// parameter is out of bounds. + /// + [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern IntPtr GetSidSubAuthority(IntPtr pSid, UInt32 nSubAuthority); + } + } +} diff --git a/SystemExtensions/SystemExtensions.csproj b/SystemExtensions/SystemExtensions.csproj index 45ce300..cb7365f 100644 --- a/SystemExtensions/SystemExtensions.csproj +++ b/SystemExtensions/SystemExtensions.csproj @@ -54,6 +54,7 @@ +