FlashPatcher/FlashPatcher/TaskService/Native/WindowsImpersonatedIdentity.cs

80 lines
2.6 KiB
C#

using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Security.Principal;
namespace Microsoft.Win32
{
/// <summary>
/// Impersonation of a user. Allows to execute code under another
/// user context.
/// Please note that the account that instantiates the Impersonator class
/// needs to have the 'Act as part of operating system' privilege set.
/// </summary>
internal class WindowsImpersonatedIdentity : IDisposable, IIdentity
{
private const int LOGON_TYPE_NEW_CREDENTIALS = 9;
private const int LOGON32_LOGON_INTERACTIVE = 2;
private const int LOGON32_PROVIDER_DEFAULT = 0;
private const int LOGON32_PROVIDER_WINNT50 = 3;
#if NETSTANDARD || NETCOREAPP
#else
private WindowsImpersonationContext impersonationContext = null;
#endif
NativeMethods.SafeTokenHandle token;
private WindowsIdentity identity = null;
/// <summary>
/// Constructor. Starts the impersonation with the given credentials.
/// Please note that the account that instantiates the Impersonator class
/// needs to have the 'Act as part of operating system' privilege set.
/// </summary>
/// <param name="userName">The name of the user to act as.</param>
/// <param name="domainName">The domain name of the user to act as.</param>
/// <param name="password">The password of the user to act as.</param>
public WindowsImpersonatedIdentity(string userName, string domainName, string password)
{
if (string.IsNullOrEmpty(userName) && string.IsNullOrEmpty(domainName) && string.IsNullOrEmpty(password))
{
identity = WindowsIdentity.GetCurrent();
}
else
{
if (NativeMethods.LogonUser(userName, domainName, password, domainName == null ? LOGON_TYPE_NEW_CREDENTIALS : LOGON32_LOGON_INTERACTIVE, domainName == null ? LOGON32_PROVIDER_WINNT50 : LOGON32_PROVIDER_DEFAULT, out token) != 0)
{
#if NETSTANDARD || NETCOREAPP
if (!NativeMethods.ImpersonateLoggedOnUser(token.DangerousGetHandle()))
throw new Win32Exception();
#else
identity = new WindowsIdentity(token.DangerousGetHandle());
impersonationContext = identity.Impersonate();
#endif
}
else
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
}
public string AuthenticationType => identity?.AuthenticationType;
public bool IsAuthenticated => identity == null ? false : identity.IsAuthenticated;
public string Name => identity == null ? null : identity.Name;
public void Dispose()
{
#if NETSTANDARD || NETCOREAPP
NativeMethods.RevertToSelf();
#else
if (impersonationContext != null)
impersonationContext.Undo();
#endif
token?.Dispose();
if (identity != null)
identity.Dispose();
}
}
}