/// <summary>
 /// This method calles LogonUser API to impersonation the user and is
 /// a wrapper around the code exposed by the delegate which makes it
 /// run while impersonating
 /// </summary>
 /// <typeparam name="TReturn">
 /// Generic return type of the delegated function
 /// </typeparam>
 /// <typeparam name="TParameter">
 /// Generic parameter of the delegated function
 /// </typeparam>
 /// <param name="userName">The user name</param>
 /// <param name="domain">Domain</param>
 /// <param name="password">Password</param>
 /// <param name="parameter">Parameter of the delegated function</param>
 /// <param name="impersonationWork">
 /// Called method while impersonating
 /// </param>
 /// <returns>The return of the delegated function</returns>
 public static TReturn Impersonate <TReturn, TParameter>(
     string userName,
     string domain,
     SecureString password,
     TParameter parameter,
     ImpersonationWorkFunction <TReturn, TParameter> impersonationWork)
 {
     return(Impersonate(
                userName,
                domain,
                password,
                parameter,
                impersonationWork,
                NativeMethod.LogonType.LOGON32_LOGON_INTERACTIVE,
                NativeMethod.LogonProvider.LOGON32_PROVIDER_DEFAULT));
 }
    public static TReturn Impersonate <TReturn, TParameter>(
        string userName,
        string domain,
        SecureString password,
        TParameter parameter,
        ImpersonationWorkFunction <TReturn, TParameter> impersonationWork,
        NativeMethod.LogonType logonMethod,
        NativeMethod.LogonProvider provider)
    {
        // Check the parameters
        if (string.IsNullOrEmpty(userName))
        {
            throw new ArgumentNullException("userName");
        }
        if (password == null)
        {
            throw new ArgumentNullException("password");
        }
        if (impersonationWork == null)
        {
            throw new ArgumentNullException("impersonationWork");
        }
        if (logonMethod < NativeMethod.LogonType.LOGON32_LOGON_INTERACTIVE |
            NativeMethod.LogonType.LOGON32_LOGON_NEW_CREDENTIALS < logonMethod)
        {
            throw new ArgumentOutOfRangeException("logonMethod");
        }
        if (provider < NativeMethod.LogonProvider.LOGON32_PROVIDER_DEFAULT |
            NativeMethod.LogonProvider.LOGON32_PROVIDER_WINNT50 < provider)
        {
            throw new ArgumentOutOfRangeException("provider");
        }

        IntPtr        passwordPtr           = IntPtr.Zero;
        SafeUserToken token                 = null;
        WindowsImpersonationContext context = null;

        try
        {
            // Convert the password to a string
            passwordPtr = Marshal.SecureStringToBSTR(password);
            IntPtr handle = IntPtr.Zero;

            // Attempts to log a user on to the local computer
            if (!NativeMethod.LogonUser(userName, domain, passwordPtr,
                                        logonMethod, provider, out handle))
            {
                throw new Win32Exception();
            }
            else
            {
                token = new SafeUserToken(ref handle);
            }
        }
        finally
        {
            // Erase the memory that the password was stored in
            if (!IntPtr.Zero.Equals(passwordPtr))
            {
                Marshal.ZeroFreeBSTR(passwordPtr);
            }
        }

        try
        {
            // Impersonate
            Debug.Assert(token != null);
            context = WindowsIdentity.Impersonate(token.DangerousGetHandle());

            // Call out to the work function
            return(impersonationWork(parameter));
        }
        finally
        {
            // Clean up
            UndoImpersonation(ref token, ref context);
        }
    }