mirror of https://github.com/dahall/Vanara.git
78 lines
3.0 KiB
C#
78 lines
3.0 KiB
C#
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
|
|
{
|
|
/// <summary>Elevate user privileges for a code block similar to a <c>lock</c> or <c>using</c> statement.</summary>
|
|
public sealed class PrivilegedCodeBlock : IDisposable
|
|
{
|
|
private bool disposed;
|
|
private readonly TOKEN_PRIVILEGES prev;
|
|
private readonly SafeHTOKEN hObj;
|
|
|
|
/// <summary>Initializes a new instance of the <see cref="PrivilegedCodeBlock"/> class.</summary>
|
|
/// <param name="systemPrivileges">The privileges.</param>
|
|
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail), SecurityCritical]
|
|
public PrivilegedCodeBlock(params SystemPrivilege[] systemPrivileges) : this(Process.GetCurrentProcess(), systemPrivileges)
|
|
{
|
|
}
|
|
|
|
/// <summary>Initializes a new instance of the <see cref="PrivilegedCodeBlock"/> class.</summary>
|
|
/// <param name="process">Process on which to enable the <see cref="SystemPrivilege"/>.</param>
|
|
/// <param name="systemPrivileges">The privileges.</param>
|
|
[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());
|
|
}
|
|
|
|
/// <summary>Finalizes an instance of the PrivilegedCodeBlock class.</summary>
|
|
[SecuritySafeCritical]
|
|
~PrivilegedCodeBlock()
|
|
{
|
|
Revert();
|
|
}
|
|
|
|
/// <summary>Disposes of an instance of the PrivilegedCodeBlock class.</summary>
|
|
/// <exception cref="System.ComponentModel.Win32Exception">Thrown when an underlying Win32 function call does not succeed.</exception>
|
|
[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);
|
|
}
|
|
|
|
/// <summary>Revert back to prior privileges.</summary>
|
|
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail), SecurityCritical]
|
|
private void Revert()
|
|
{
|
|
if (disposed) return;
|
|
lock (hObj)
|
|
{
|
|
RuntimeHelpers.PrepareConstrainedRegions();
|
|
hObj.AdjustPrivileges(prev);
|
|
}
|
|
hObj.Dispose();
|
|
disposed = true;
|
|
}
|
|
}
|
|
} |