using System; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.ConstrainedExecution; using System.Security; using Vanara.InteropServices; using static Vanara.PInvoke.AdvApi32; namespace Vanara.Security.AccessControl { /// Elevate user privileges for a code block similar to a lock or using statement. public sealed class PrivilegedCodeBlock : IDisposable { private bool disposed; private readonly TOKEN_PRIVILEGES prev; private readonly SafeHTOKEN hObj; /// Initializes a new instance of the class. /// The privileges. [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail), SecurityCritical] public PrivilegedCodeBlock(params SystemPrivilege[] systemPrivileges) : this(Process.GetCurrentProcess(), systemPrivileges) { } /// Initializes a new instance of the class. /// Process on which to enable the . /// The privileges. [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail), SecurityCritical] public PrivilegedCodeBlock(Process process, params SystemPrivilege[] systemPrivileges) { if (systemPrivileges == null || systemPrivileges.Length == 0) return; RuntimeHelpers.PrepareConstrainedRegions(); hObj = SafeHTOKEN.FromProcess(process, TokenAccess.TOKEN_ADJUST_PRIVILEGES | TokenAccess.TOKEN_QUERY); if (systemPrivileges.Length == 1) prev = hObj.AdjustPrivilege(systemPrivileges[0], PrivilegeAttributes.SE_PRIVILEGE_ENABLED); else prev = hObj.AdjustPrivileges(systemPrivileges.Select(p => new PrivilegeAndAttributes(p, PrivilegeAttributes.SE_PRIVILEGE_ENABLED)).ToArray()); } /// Finalizes an instance of the PrivilegedCodeBlock class. [SecuritySafeCritical] ~PrivilegedCodeBlock() { Revert(); } /// Disposes of an instance of the PrivilegedCodeBlock class. /// Thrown when an underlying Win32 function call does not succeed. [SecurityCritical] public void Dispose() { Revert(); GC.SuppressFinalize(this); } internal static string EnvironmentGetResourceString(string key, params object[] values) { var str = new System.Resources.ResourceManager(typeof(Environment)).GetString(key); return values.Length == 0 || str == null ? str : string.Format(CultureInfo.CurrentCulture, str, values); } /// Revert back to prior privileges. [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail), SecurityCritical] private void Revert() { if (disposed) return; lock (hObj) { RuntimeHelpers.PrepareConstrainedRegions(); hObj.AdjustPrivileges(prev); } hObj.Dispose(); disposed = true; } } }