File: system\security\principal\windowsimpersonationcontext.cs
Project: ndp\clr\src\bcl\mscorlib.csproj (mscorlib)
// ==++==
// 
//   Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// ==--==
// <OWNER>Microsoft</OWNER>
// 
 
//
// WindowsImpersonationContext.cs
//
// Representation of an impersonation context.
//
 
namespace System.Security.Principal
{
    using Microsoft.Win32;
    using Microsoft.Win32.SafeHandles;
    using System.Runtime.InteropServices;
#if FEATURE_CORRUPTING_EXCEPTIONS
    using System.Runtime.ExceptionServices;
#endif // FEATURE_CORRUPTING_EXCEPTIONS
    using System.Security.Permissions;
    using System.Runtime.ConstrainedExecution;
    using System.Runtime.Versioning;
    using System.Diagnostics.Contracts;
    using System.Diagnostics.CodeAnalysis;
 
    [System.Runtime.InteropServices.ComVisible(true)]
    public class WindowsImpersonationContext : IDisposable {
        [System.Security.SecurityCritical] // auto-generated
        private SafeAccessTokenHandle m_safeTokenHandle = SafeAccessTokenHandle.InvalidHandle;
        private WindowsIdentity m_wi;
        private FrameSecurityDescriptor m_fsd;
 
        [System.Security.SecurityCritical]  // auto-generated
        private WindowsImpersonationContext () {}
 
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
        internal WindowsImpersonationContext (SafeAccessTokenHandle safeTokenHandle, WindowsIdentity wi, bool isImpersonating, FrameSecurityDescriptor fsd) {
            if (safeTokenHandle.IsInvalid)
                throw new ArgumentException(Environment.GetResourceString("Argument_InvalidImpersonationToken"));
            Contract.EndContractBlock();
 
            if (isImpersonating) {
                if (!Win32Native.DuplicateHandle(Win32Native.GetCurrentProcess(),
                                                 safeTokenHandle,
                                                 Win32Native.GetCurrentProcess(),
                                                 ref m_safeTokenHandle,
                                                 0,
                                                 true,
                                                 Win32Native.DUPLICATE_SAME_ACCESS))
                    throw new SecurityException(Win32Native.GetMessage(Marshal.GetLastWin32Error()));
                m_wi = wi;
            }
            m_fsd = fsd;
        }
 
        // Revert to previous impersonation (the only public method).
        [System.Security.SecuritySafeCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
        public void Undo () {
            int hr = 0;
            if (m_safeTokenHandle.IsInvalid) { // the thread was not initially impersonating
                hr = Win32.RevertToSelf();
                if (hr < 0)
                    Environment.FailFast(Win32Native.GetMessage(hr));
            } else {
                hr = Win32.RevertToSelf();
                if (hr < 0)
                    Environment.FailFast(Win32Native.GetMessage(hr));
                hr = Win32.ImpersonateLoggedOnUser(m_safeTokenHandle);
                if (hr < 0)
                    throw new SecurityException(Win32Native.GetMessage(hr));
            }
            WindowsIdentity.UpdateThreadWI(m_wi);
            if (m_fsd != null)
                m_fsd.SetTokenHandles(null, null);
        }
 
        // Non-throwing version that does not new any exception objects. To be called when reliability matters
        [System.Security.SecurityCritical]  // auto-generated
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
#if FEATURE_CORRUPTING_EXCEPTIONS
        [HandleProcessCorruptedStateExceptions] // 
        [SuppressMessage("Microsoft.Security", "CA2153:DoNotCatchCorruptedStateExceptionsInGeneralHandlers", Justification = "Reviewed for security")]
#endif // FEATURE_CORRUPTING_EXCEPTIONS
        internal bool UndoNoThrow()
        {
            bool bRet = false;
            try
            {
                int hr = 0;
                if (m_safeTokenHandle.IsInvalid) 
                { // the thread was not initially impersonating
                    hr = Win32.RevertToSelf();
                    if (hr < 0)
                        Environment.FailFast(Win32Native.GetMessage(hr));
                } 
                else
                {
                    hr = Win32.RevertToSelf();
                    if (hr >= 0)
                    {
                        hr = Win32.ImpersonateLoggedOnUser(m_safeTokenHandle);
                    }
                    else
                    {
                        Environment.FailFast(Win32Native.GetMessage(hr));
                    }
                }
                bRet = (hr >= 0);
                if (m_fsd != null)
                    m_fsd.SetTokenHandles(null,null);
            }
            catch (Exception ex)
            {
                if (!AppContextSwitches.UseLegacyExecutionContextBehaviorUponUndoFailure)
                {
                    // Fail fast since we can't continue safely
                    Environment.FailFast(Environment.GetResourceString("ExecutionContext_UndoFailed"), ex);
                }
                bRet = false;
            }
            return bRet;
        }
 
        //
        // IDisposable interface.
        //
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [ComVisible(false)]
        protected virtual void Dispose(bool disposing) {
            if (disposing) {
                if (m_safeTokenHandle != null && !m_safeTokenHandle.IsClosed) {
                    Undo();
                    m_safeTokenHandle.Dispose();
                }
            }
        }
 
        [ComVisible(false)]
        public void Dispose () {
            Dispose(true);
        }
    }
}