Impersonation in Microsoft Dot Net

Usage

string domain = "ExampleDomain";
string userName = "ExampleUserName";
string password = "ExamplePassword"; 

using (Impersonation impersonation = new Impersonation(domain, userName, password))
{
      // impersonation occuring in here 
         Console.WriteLine(System.Security.Principal.WindowsIdentity.GetCurrent().Name);
} 

Implementation
using System;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Security.Principal;

namespace ExampleNameSpace
{
     public class Impersonation : IDisposable
        {
            private bool _disposed = false;
            private WindowsImpersonationContext _wc;

            #region Win32 Interop
            // Win32 declarations (constants, enumerations, functions etc.)
            public const int LOGON32_LOGON_INTERACTIVE = 2;
            public const int LOGON32_PROVIDER_DEFAULT = 0;

            [DllImport("kernel32.dll", CallingConvention = CallingConvention.Winapi, SetLastError = true)]
            public static extern int CloseHandle(
                IntPtr handle);

            [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            public static extern int DuplicateToken(IntPtr hToken,
                int impersonationLevel,
                ref IntPtr hNewToken);

            [DllImport("advapi32.dll")]
            public static extern int LogonUserA(String lpszUserName,
                String lpszDomain,
                String lpszPassword,
                int dwLogonType,
                int dwLogonProvider,
                ref IntPtr phToken);

            [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            public static extern bool RevertToSelf();
            #endregion

            /// <summary>
            /// Constructor begins impersonation based on user credentials passed in. 
            /// </summary>
            /// <param name="domain">Windows Domain</param>
            /// <param name="userName">Windows username</param>
            /// <param name="password">Windows password</param>
            public Impersonation(string domain, string userName, string password)
            {
                if (!string.IsNullOrEmpty(password))
                {
                    _wc = WindowsIdentity.GetCurrent().Impersonate();
                    ImpersonateValidUser(domain, userName, password);
                }
            }

            /// <summary>
            /// This destructor will run only if the Dispose method does not get called.
            /// </summary>
            ~Impersonation()
            {
                Dispose(false);
            }

            /// <summary>
            /// Dispose(bool disposing) executes in two distinct scenarios. If disposing equals true, the method
            /// has been called directly or indirectly by a user's code. Managed and unmanaged resources can be
            /// disposed. If disposing equals false, the method has been called by the runtime from inside the
            /// finalizer and you should not reference other objects. Only unmanaged resources can be disposed.
            /// </summary>
            /// <param name="disposing">True if function called from user code, false if called from finalizer.</param>
            private void Dispose(bool disposing)
            {
                // Check to see if Dispose has already been called
                if (!_disposed)
                {
                    // If disposing equals true, dispose all managed and unmanaged resources
                    if (disposing)
                    {
                        // Dispose managed resources (there are none)
                    }

                    // Clean up unmanaged resources here (there are none)

                    // Reset impersonation
                    UndoImpersonation();
                }
                _disposed = true;
            }

            /// <summary>
            /// Implement IDisposable.
            /// </summary>
            public void Dispose()
            {
                // Clean up this object
                Dispose(true);

                // Take this object off the finalization queue and prevent finalization code for this object
                // from executing a second time.
                GC.SuppressFinalize(this);
            }

            /// <summary>
            /// This function can be used to impersonate a specific user while a section of code is run.
            /// This code is taken from the Microsoft Knowledge Base, article KB30615, "How to implement
            /// impersonation in an ASP.NET application".
            /// </summary>
            /// <param name="domain">Windows domain</param>
            /// <param name="userName">The user that is being impersonated.  This can be a user SAM account
            /// name or a user principal name. Whether or not UPN is selected is detected by looking for an
            /// occurrence of the @ character in userName.</param>
            /// <param name="password">The user's password.</param>
            /// <returns>True if impersonation works, false if impersonation fails.</returns>
            [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
            public bool ImpersonateValidUser(string domain, string userName, string password)
            {
                WindowsIdentity tempWindowsIdentity;
                IntPtr token = IntPtr.Zero;
                IntPtr tokenDuplicate = IntPtr.Zero;

                if (RevertToSelf())
                {   
                    if (LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token) != 0)
                    {
                        if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                        {
                            tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                            _wc = tempWindowsIdentity.Impersonate();

                            if (_wc != null)
                            {
                                CloseHandle(token);
                                CloseHandle(tokenDuplicate);
                                return true;
                            }
                        }
                    }
                }

                if (token != IntPtr.Zero)
                    CloseHandle(token);
                if (tokenDuplicate != IntPtr.Zero)
                    CloseHandle(tokenDuplicate);
                return false;
            }

            /// <summary>
            /// Called after ImpersonateValidUser (see above).
            /// </summary>
            /// <param name="impersonationContext">An object that represents the Windows user prior to an
            /// impersonation operation.</param>
            public void UndoImpersonation()
            {
                if (_wc != null)
                    _wc.Undo();
            }
        } 
 
}