﻿// Decompiled with JetBrains decompiler
// Type: System.Security.Principal.WindowsImpersonationContext
// Assembly: mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// MVID: 255ABCDF-D9D6-4E3D-BAD4-F74D4CE3D7A8
// Assembly location: C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll

using Microsoft.Win32;
using Microsoft.Win32.SafeHandles;
using System;
using System.Runtime;
using System.Runtime.ConstrainedExecution;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;
using System.Security;

namespace System.Security.Principal
{
  /// <summary>
  /// Represents the Windows user prior to an impersonation operation.
  /// </summary>
  [ComVisible(true)]
  public class WindowsImpersonationContext : IDisposable
  {
    [SecurityCritical]
    private SafeTokenHandle m_safeTokenHandle = SafeTokenHandle.InvalidHandle;
    private WindowsIdentity m_wi;
    private FrameSecurityDescriptor m_fsd;

    [SecurityCritical]
    internal WindowsImpersonationContext(SafeTokenHandle safeTokenHandle, WindowsIdentity wi, bool isImpersonating, FrameSecurityDescriptor fsd)
    {
      if (safeTokenHandle.IsInvalid)
        throw new ArgumentException(Environment.GetResourceString("Argument_InvalidImpersonationToken"));
      if (isImpersonating)
      {
        if (!Win32Native.DuplicateHandle(Win32Native.GetCurrentProcess(), safeTokenHandle, Win32Native.GetCurrentProcess(), out this.m_safeTokenHandle, 0U, true, 2U))
          throw new SecurityException(Win32Native.GetMessage(Marshal.GetLastWin32Error()));
        this.m_wi = wi;
      }
      this.m_fsd = fsd;
    }

    [SecurityCritical]
    private WindowsImpersonationContext()
    {
    }

    /// <summary>
    /// Reverts the user context to the Windows user represented by this object.
    /// </summary>
    /// <exception cref="T:System.Security.SecurityException">An attempt is made to use this method for any purpose other than to revert identity to self. </exception>
    [SecuritySafeCritical]
    public void Undo()
    {
      if (this.m_safeTokenHandle.IsInvalid)
      {
        int errorCode = Win32.RevertToSelf();
        if (errorCode < 0)
          Environment.FailFast(Win32Native.GetMessage(errorCode));
      }
      else
      {
        int errorCode1 = Win32.RevertToSelf();
        if (errorCode1 < 0)
          Environment.FailFast(Win32Native.GetMessage(errorCode1));
        int errorCode2 = Win32.ImpersonateLoggedOnUser(this.m_safeTokenHandle);
        if (errorCode2 < 0)
          throw new SecurityException(Win32Native.GetMessage(errorCode2));
      }
      WindowsIdentity.UpdateThreadWI(this.m_wi);
      if (this.m_fsd == null)
        return;
      this.m_fsd.SetTokenHandles((SafeTokenHandle) null, (SafeTokenHandle) null);
    }

    [HandleProcessCorruptedStateExceptions]
    [SecurityCritical]
    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
    internal bool UndoNoThrow()
    {
      bool flag;
      try
      {
        int errorCode;
        if (this.m_safeTokenHandle.IsInvalid)
        {
          errorCode = Win32.RevertToSelf();
          if (errorCode < 0)
            Environment.FailFast(Win32Native.GetMessage(errorCode));
        }
        else
        {
          errorCode = Win32.RevertToSelf();
          if (errorCode >= 0)
            errorCode = Win32.ImpersonateLoggedOnUser(this.m_safeTokenHandle);
          else
            Environment.FailFast(Win32Native.GetMessage(errorCode));
        }
        flag = errorCode >= 0;
        if (this.m_fsd != null)
          this.m_fsd.SetTokenHandles((SafeTokenHandle) null, (SafeTokenHandle) null);
      }
      catch
      {
        flag = false;
      }
      return flag;
    }

    /// <summary>
    /// Releases the unmanaged resources used by the <see cref="T:System.Security.Principal.WindowsImpersonationContext"/> and optionally releases the managed resources.
    /// </summary>
    /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources. </param>
    [SecuritySafeCritical]
    [ComVisible(false)]
    protected virtual void Dispose(bool disposing)
    {
      if (!disposing || this.m_safeTokenHandle == null || this.m_safeTokenHandle.IsClosed)
        return;
      this.Undo();
      this.m_safeTokenHandle.Dispose();
    }

    /// <summary>
    /// Releases all resources used by the <see cref="T:System.Security.Principal.WindowsImpersonationContext"/>.
    /// </summary>
    [ComVisible(false)]
    [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
    public void Dispose()
    {
      this.Dispose(true);
    }
  }
}
