Click here to Skip to main content
Licence CPOL
First Posted 11 Apr 2005
Views 262,811
Downloads 8,819
Bookmarked 168 times

A small C# Class for impersonating a User

By | 11 Apr 2005 | Article
Introduced a class that simplifies Windows Impersonation in C#.

Introduction

The term "Impersonation" in a programming context refers to a technique that executes the code under another user context than the user who originally started an application, i.e. the user context is temporarily changed once or multiple times during the execution of an application.

The reason for doing this is to perform tasks that the current user context of an application is not allowed to do. Of course you could grant the user executing an application more privileges, but usually this is a bad idea (due to security constraints) or impossible (e.g. if you don't have full administrative access to a machine to do so).

This article presents an easy-to-use class to impersonate a user. While writing this, I found out that Marc Merrit had written an article ("Windows Impersonation using C#") that uses the same Microsoft knowledge base code (from Q306158) that I have used. The code presented in my article differs in the fact that you could use it inside a using-block to safely release resources and that I use slightly more exceptions to report errors. But from a first look, both his and my article do the same job, so it's up to you to decide what to do.

(For the latest changes, please see the History section below).

Background

I wrote the Impersonator class because of a need to write a web page with ASP.NET to make a server reboot. In order to do this, I needed to impersonate the part of my code that does the actual reboot.

The constructor of the class internally calls the Windows function LogonUser through P/Invoke. Please see the MSDN documentation of the function for a full description of all three parameters (username, domain, password) to the constructor.

Please note: The user context that initiates the impersonation (i.e. not the user context to which it is switched to) needs to have the "Act as part of operating system" privilege set.

Using the code

To use the code, you simply construct the Impersonator class and pass the username, the domain and the password to the constructor. If you place an instance of the class inside a using-block, you need no further steps.

The following is a schematic example of how to use the class:

... 
using ( new Impersonator( "myUsername", "myDomainname", "myPassword" ) )
{
   ...
   
   <code that executes under the new context>
  
   ...
}
  
...

An example project demonstrating the technique is included in the download of this article (please look at the "Program.cs" for the main demonstration source file). Also the complete source code of the class is included inside the source file "Impersonator.cs".

To include the Impersonator class into your project, simply copy and add the source file "Impersonator.cs" to your project, so that it gets compiled with your project.

Conclusion

In this article, I've shown you a small class to quickly and easily impersonate a part of your code to run under another user context. Hopefully you'll find this class useful.

For questions, comments and remarks, please use the commenting section at the bottom of this article.

References

In addition to the links in the article, the following references might be of interest:

  1. Google search for "Windows Impersonation"

History

  • 2005-04-11: Created first version of article.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Uwe Keim

Chief Technology Officer
Zeta Producer Desktop CMS
Germany Germany

Member

Uwe does programming since 1989 with experiences in Assembler, C++, MFC and lots of web- and database stuff and now uses ASP.NET and C# extensively, too. He is also teached programming to students at the local university.
 
In his free time, he does climbing, running and mountain biking. You can watch him most of the day (and probably night) programming.
 
Some cool, free software from us:
 
Free Test Management Software - Intuitive, competitive, Test Plans. Download now!  
Homepage erstellen - Intuitive, very easy to use. Download now!  
Send large Files online for free by Email
Some random fun stuff in German


Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralCould not find a part of the path PinmemberRugbyLeague2:35 15 Aug '08  
GeneralRe: Could not find a part of the path Pinmemberfiniduck1:27 30 Oct '08  
GeneralExcellent PinmemberEmad Attia7:04 30 Jul '08  
GeneralDoesn't work on Windows 2000 Pinmemberweitech21:50 12 Jun '08  
GeneralRe: Doesn't work on Windows 2000 Pinmemberjuggler3:44 30 Nov '09  
GeneralExtended Version PinsitebuilderUwe Keim6:27 22 May '08  
GeneralRe: Extended Version PinsitebuilderUwe Keim6:27 22 May '08  
namespace Zeta.EnterpriseLibrary.Tools
{
     #region Using directives.
     // ----------------------------------------------------------------------
 
     using System;
     using System.ComponentModel;
     using System.Diagnostics;
     using System.Runtime.InteropServices;
     using System.Security;
     using System.Security.Principal;
 
     // ----------------------------------------------------------------------
     #endregion
 
     /////////////////////////////////////////////////////////////////////////
 
     /// <summary>
     /// Impersonation of a user. Allows to execute code under another
     /// user context.
     /// The account that instantiates the Impersonator class
     /// needs to have the 'Act as part of operating system' privilege set.
     /// </summary>
     /// <remarks>    
     /// This class is based on the information in the Microsoft knowledge base
     /// article http://support.microsoft.com/default.aspx?scid=kb;en-us;Q306158
     ///
     /// Encapsulate an instance into a using-directive like e.g.:
     ///
     ///          ...
     ///          using ( new Impersonator( "myUsername", "myDomainname", "myPassword" ) )
     ///          {
     ///               ...
     ///               [code that executes under the new context]
     ///               ...
     ///          }
     ///          ...
     /// </remarks>
     public class Impersonator :
          IDisposable
     {
          #region Public methods.
          // ------------------------------------------------------------------
 
          /// <summary>
          /// Initializes a new instance of the <see cref="Impersonator"/> class.
          /// </summary>
          public Impersonator()
          {
          }
 
          /// <summary>
          /// Constructor. Starts the impersonation with the given credentials.
          /// 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>
          /// <param name="profileBehaviour">The profile behaviour.</param>
          public Impersonator(
               string userName,
               string domainName,
               string password,
               ProfileBehaviour profileBehaviour )
          {
               ImpersonateValidUser(
                    userName,
                    domainName,
                    password,
                    LoginType.Interactive,
                    profileBehaviour );
          }
 
          /// <summary>
          /// Constructor. Starts the impersonation with the given credentials.
          /// 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>
          /// <param name="loginType">The login type.</param>
          /// <param name="profileBehaviour">The profile behaviour.</param>
          public Impersonator(
               string userName,
               string domainName,
               string password,
               LoginType loginType,
               ProfileBehaviour profileBehaviour )
          {
               ImpersonateValidUser(
                    userName,
                    domainName,
                    password,
                    loginType,
                    profileBehaviour );
          }
 
          /// <summary>
          /// Constructor. Starts the impersonation with the given credentials.
          /// 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>
          /// <param name="profileBehaviour">The profile behaviour.</param>
          public Impersonator(
               string userName,
               string domainName,
               SecureString password,
               ProfileBehaviour profileBehaviour )
          {
               ImpersonateValidUser(
                    userName,
                    domainName,
                    password,
                    LoginType.Interactive,
                    profileBehaviour );
          }
 
          /// <summary>
          /// Constructor. Starts the impersonation with the given credentials.
          /// 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>
          /// <param name="loginType">The login type.</param>
          /// <param name="profileBehaviour">The profile behaviour.</param>
          public Impersonator(
               string userName,
               string domainName,
               SecureString password,
               LoginType loginType,
               ProfileBehaviour profileBehaviour )
          {
               ImpersonateValidUser(
                    userName,
                    domainName,
                    password,
                    loginType,
                    profileBehaviour );
          }
 
          /// <summary>
          /// Constructor. Starts the impersonation with the given credentials.
          /// 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 Impersonator(
               string userName,
               string domainName,
               string password )
          {
               ImpersonateValidUser(
                    userName,
                    domainName,
                    password,
                    LoginType.Interactive,
                    ProfileBehaviour.DontLoad );
          }
 
          /// <summary>
          /// Constructor. Starts the impersonation with the given credentials.
          /// 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>
          /// <param name="loginType">The login type.</param>
          public Impersonator(
               string userName,
               string domainName,
               string password,
               LoginType loginType )
          {
               ImpersonateValidUser(
                    userName,
                    domainName,
                    password,
                    loginType,
                    ProfileBehaviour.DontLoad );
          }
 
          /// <summary>
          /// Constructor. Starts the impersonation with the given credentials.
          /// 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 Impersonator(
               string userName,
               string domainName,
               SecureString password )
          {
               ImpersonateValidUser(
                    userName,
                    domainName,
                    password,
                    LoginType.Interactive,
                    ProfileBehaviour.DontLoad );
          }
 
          /// <summary>
          /// Constructor. Starts the impersonation with the given credentials.
          /// 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>
          /// <param name="loginType">The login type.</param>
          public Impersonator(
               string userName,
               string domainName,
               SecureString password,
               LoginType loginType )
          {
               ImpersonateValidUser(
                    userName,
                    domainName,
                    password,
                    loginType,
                    ProfileBehaviour.DontLoad );
          }
 
          /// <summary>
          /// Starts the impersonation with the given credentials.
          /// 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>
          /// <param name="profileBehaviour">The profile behaviour.</param>
          public void Impersonate(
               string userName,
               string domainName,
               string password,
               ProfileBehaviour profileBehaviour )
          {
               ImpersonateValidUser(
                    userName,
                    domainName,
                    password,
                    LoginType.Interactive,
                    profileBehaviour );
          }
 
          /// <summary>
          /// Starts the impersonation with the given credentials.
          /// 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>
          /// <param name="loginType">The login type.</param>
          /// <param name="profileBehaviour">The profile behaviour.</param>
          public void Impersonate(
               string userName,
               string domainName,
               string password,
               LoginType loginType,
               ProfileBehaviour profileBehaviour )
          {
               ImpersonateValidUser(
                    userName,
                    domainName,
                    password,
                    loginType,
                    profileBehaviour );
          }
 
          /// <summary>
          /// Starts the impersonation with the given credentials.
          /// 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>
          /// <param name="profileBehaviour">The profile behaviour.</param>
          public void Impersonate(
               string userName,
               string domainName,
               SecureString password,
               ProfileBehaviour profileBehaviour )
          {
               ImpersonateValidUser(
                    userName,
                    domainName,
                    password,
                    LoginType.Interactive,
                    profileBehaviour );
          }
 
          /// <summary>
          /// Starts the impersonation with the given credentials.
          /// 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>
          /// <param name="loginType">The login type.</param>
          /// <param name="profileBehaviour">The profile behaviour.</param>
          public void Impersonate(
               string userName,
               string domainName,
               SecureString password,
               LoginType loginType,
               ProfileBehaviour profileBehaviour )
          {
               ImpersonateValidUser(
                    userName,
                    domainName,
                    password,
                    loginType,
                    profileBehaviour );
          }
 
          /// <summary>
          /// Starts the impersonation with the given credentials.
          /// 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 void Impersonate(
               string userName,
               string domainName,
               string password )
          {
               ImpersonateValidUser(
                    userName,
                    domainName,
                    password,
                    LoginType.Interactive,
                    ProfileBehaviour.DontLoad );
          }
 
          /// <summary>
          /// Starts the impersonation with the given credentials.
          /// 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>
          /// <param name="loginType">The login type.</param>
          public void Impersonate(
               string userName,
               string domainName,
               string password,
               LoginType loginType )
          {
               ImpersonateValidUser(
                    userName,
                    domainName,
                    password,
                    loginType,
                    ProfileBehaviour.DontLoad );
          }
 
          /// <summary>
          /// Starts the impersonation with the given credentials.
          /// 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 void Impersonate(
               string userName,
               string domainName,
               SecureString password )
          {
               ImpersonateValidUser(
                    userName,
                    domainName,
                    password,
                    LoginType.Interactive,
                    ProfileBehaviour.DontLoad );
          }
 
          /// <summary>
          /// Starts the impersonation with the given credentials.
          /// 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>
          /// <param name="loginType">The login type.</param>
          public void Impersonate(
               string userName,
               string domainName,
               SecureString password,
               LoginType loginType )
          {
               ImpersonateValidUser(
                    userName,
                    domainName,
                    password,
                    loginType,
                    ProfileBehaviour.DontLoad );
          }
 
          /// <summary>
          /// Undoes the impersonation. Safe to call even if not yet
          /// impersonized.
          /// </summary>
          public void Undo()
          {
               UndoImpersonation();
          }
 
          // ------------------------------------------------------------------
          #endregion
 
          #region IDisposable member.
          // ------------------------------------------------------------------
 
          /// <summary>
          /// Performs application-defined tasks associated with freeing,
          /// releasing, or resetting unmanaged resources.
          /// </summary>
          public void Dispose()
          {
               UndoImpersonation();
               GC.SuppressFinalize( this );
          }
 
          /// <summary>
          /// Releases unmanaged resources and performs other cleanup operations before the
          /// <see cref="Impersonator"/> is reclaimed by garbage collection.
          /// </summary>
          ~Impersonator()
          {
               UndoImpersonation();
          }
 
          // ------------------------------------------------------------------
          #endregion
 
          #region P/Invoke.
          // ------------------------------------------------------------------
 
          /// <summary>
          /// Logons the user.
          /// </summary>
          /// <param name="lpszUserName">Name of the LPSZ user.</param>
          /// <param name="lpszDomain">The LPSZ domain.</param>
          /// <param name="lpszPassword">The LPSZ password.</param>
          /// <param name="dwLogonType">Type of the dw logon.</param>
          /// <param name="dwLogonProvider">The dw logon provider.</param>
          /// <param name="phToken">The ph token.</param>
          /// <returns></returns>
          [DllImport( @"advapi32.dll", CharSet = CharSet.Auto, SetLastError = true )]
          private static extern int LogonUser(
               string lpszUserName,
               string lpszDomain,
               string lpszPassword,
               int dwLogonType,
               int dwLogonProvider,
               ref IntPtr phToken );
 
          /// <summary>
          /// Logons the user2.
          /// </summary>
          /// <param name="lpszUserName">Name of the LPSZ user.</param>
          /// <param name="lpszDomain">The LPSZ domain.</param>
          /// <param name="Password">The password.</param>
          /// <param name="dwLogonType">Type of the dw logon.</param>
          /// <param name="dwLogonProvider">The dw logon provider.</param>
          /// <param name="phToken">The ph token.</param>
          /// <returns></returns>
          [DllImport( @"advapi32.dll", EntryPoint = @"LogonUser", CharSet = CharSet.Unicode, SetLastError = true )]
          private static extern int LogonUser2(
               string lpszUserName,
               string lpszDomain,
               IntPtr Password,
               int dwLogonType,
               int dwLogonProvider,
               ref IntPtr phToken );
 
          /// <summary>
          /// Duplicates the token.
          /// </summary>
          /// <param name="hToken">The h token.</param>
          /// <param name="impersonationLevel">The impersonation level.</param>
          /// <param name="hNewToken">The h new token.</param>
          /// <returns></returns>
          [DllImport( @"advapi32.dll", CharSet = CharSet.Auto, SetLastError = true )]
          private static extern int DuplicateToken(
               IntPtr hToken,
               int impersonationLevel,
               ref IntPtr hNewToken );
 
          /// <summary>
          /// Reverts to self.
          /// </summary>
          /// <returns></returns>
          [DllImport( @"advapi32.dll", CharSet = CharSet.Auto, SetLastError = true )]
          private static extern bool RevertToSelf();
 
          /// <summary>
          /// Closes the handle.
          /// </summary>
          /// <param name="handle">The handle.</param>
          /// <returns></returns>
          [DllImport( @"kernel32.dll", CharSet = CharSet.Auto, SetLastError = true )]
          private static extern bool CloseHandle(
               IntPtr handle );
 
          /// <summary>
          ///
          /// </summary>
          private const int LOGON32_PROVIDER_DEFAULT = 0;
 
          [DllImport( @"userenv.dll", SetLastError = true, CharSet = CharSet.Auto )]
          private static extern bool LoadUserProfile(
               IntPtr hToken,
               ref PROFILEINFO lpProfileInfo );
 
          [DllImport( @"userenv.dll", SetLastError = true, CharSet = CharSet.Auto )]
          private static extern bool UnloadUserProfile(
               IntPtr hToken,
               IntPtr hProfile );
 
          [StructLayout( LayoutKind.Sequential )]
          private struct PROFILEINFO
          {
               public int dwSize;
               public int dwFlags;
               [MarshalAs( UnmanagedType.LPTStr )]
               public String lpUserName;
               [MarshalAs( UnmanagedType.LPTStr )]
               public String lpProfilePath;
               [MarshalAs( UnmanagedType.LPTStr )]
               public String lpDefaultPath;
               [MarshalAs( UnmanagedType.LPTStr )]
               public String lpServerName;
               [MarshalAs( UnmanagedType.LPTStr )]
               public String lpPolicyPath;
               public IntPtr hProfile;
          }
 
          // ------------------------------------------------------------------
          #endregion
 
          #region Private methods.
          // ------------------------------------------------------------------
 
          /// <summary>
          /// Does the actual impersonation.
          /// </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>
          /// <param name="loginType">Type of the login.</param>
          /// <param name="profileBehaviour">The profile behaviour.</param>
          private void ImpersonateValidUser(
               string userName,
               string domainName,
               string password,
               LoginType loginType,
               ProfileBehaviour profileBehaviour )
          {
               Trace.TraceInformation(
                    string.Format(
                    @"[Impersonation] About to impersonate as domain '{0}', user '{1}'.",
                    domainName,
                    userName ) );
 
               try
               {
                    if ( domainName != null && domainName.Length <= 0 )
                    {
                         domainName = null;
                    }
 
                    IntPtr token = IntPtr.Zero;
 
                    try
                    {
                         if ( RevertToSelf() )
                         {
                              if ( LogonUser(
                                   userName,
                                   domainName,
                                   password,
                                   (int)loginType,
                                   LOGON32_PROVIDER_DEFAULT,
                                   ref token ) != 0 )
                              {
                                   if ( DuplicateToken( token, 2, ref _impersonationToken ) != 0 )
                                   {
                                        CheckLoadProfile( profileBehaviour );
 
                                        WindowsIdentity tempWindowsIdentity =
                                             new WindowsIdentity( _impersonationToken );
                                        _impersonationContext =
                                             tempWindowsIdentity.Impersonate();
                                   }
                                   else
                                   {
                                        int le = Marshal.GetLastWin32Error();
                                        throw new Win32Exception( le );
                                   }
                              }
                              else
                              {
                                   int le = Marshal.GetLastWin32Error();
                                   throw new Win32Exception( le );
                              }
                         }
                         else
                         {
                              int le = Marshal.GetLastWin32Error();
                              throw new Win32Exception( le );
                         }
                    }
                    finally
                    {
                         if ( token != IntPtr.Zero )
                         {
                              CloseHandle( token );
                         }
                    }
               }
               catch ( Exception x )
               {
                    Trace.TraceError(
                         string.Format(
                         @"[Impersonation] Error impersonating as domain '{0}', user '{1}'.",
                         domainName,
                         userName ),
                         x );
 
                    throw;
               }
 
               Trace.TraceInformation(
                    string.Format(
                    @"[Impersonation] Successfully impersonated as domain '{0}', user '{1}'.",
                    domainName,
                    userName ) );
          }
 
          /// <summary>
          /// Does the actual impersonation.
          /// </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>
          /// <param name="loginType">Type of the login.</param>
          /// <param name="profileBehaviour">The profile behaviour.</param>
          private void ImpersonateValidUser(
               string userName,
               string domainName,
               SecureString password,
               LoginType loginType,
               ProfileBehaviour profileBehaviour )
          {
               Trace.TraceInformation(
                    string.Format(
                    @"[Impersonation] About to impersonate as domain '{0}', user '{1}'.",
                    domainName,
                    userName ) );
 
               try
               {
                    if ( domainName != null && domainName.Length <= 0 )
                    {
                         domainName = null;
                    }
 
                    IntPtr token = IntPtr.Zero;
                    IntPtr passwordPtr = IntPtr.Zero;
 
                    try
                    {
                         if ( RevertToSelf() )
                         {
                              // Marshal the SecureString to unmanaged memory.
                              passwordPtr =
                                   Marshal.SecureStringToGlobalAllocUnicode( password );
 
                              if ( LogonUser2(
                                   userName,
                                   domainName,
                                   passwordPtr,
                                   (int)loginType,
                                   LOGON32_PROVIDER_DEFAULT,
                                   ref token ) != 0 )
                              {
                                   if ( DuplicateToken( token, 2, ref _impersonationToken ) != 0 )
                                   {
                                        CheckLoadProfile( profileBehaviour );
 
                                        WindowsIdentity tempWindowsIdentity =
                                             new WindowsIdentity( _impersonationToken );
                                        _impersonationContext =
                                             tempWindowsIdentity.Impersonate();
                                   }
                                   else
                                   {
                                        int le = Marshal.GetLastWin32Error();
                                        throw new Win32Exception( le );
                                   }
                              }
                              else
                              {
                                   int le = Marshal.GetLastWin32Error();
                                   throw new Win32Exception( le );
                              }
                         }
                         else
                         {
                              int le = Marshal.GetLastWin32Error();
                              throw new Win32Exception( le );
                         }
                    }
                    finally
                    {
                         if ( token != IntPtr.Zero )
                         {
                              CloseHandle( token );
                         }
 
                         // Zero-out and free the unmanaged string reference.
                         Marshal.ZeroFreeGlobalAllocUnicode( passwordPtr );
                    }
               }
               catch ( Exception x )
               {
                    Trace.TraceError(
                         string.Format(
                         @"[Impersonation] Error impersonating as domain '{0}', user '{1}'.",
                         domainName,
                         userName ),
                         x );
 
                    throw;
               }
 
               Trace.TraceInformation(
                    string.Format(
                    @"[Impersonation] Successfully impersonated as domain '{0}', user '{1}'.",
                    domainName,
                    userName ) );
          }
 
          /// <summary>
          /// Checks and loads the load profile.
          /// </summary>
          private void CheckLoadProfile(
               ProfileBehaviour profileBehaviour )
          {
               if ( profileBehaviour == ProfileBehaviour.Load )
               {
                    _profileInfo = new PROFILEINFO();
                    _profileInfo.dwSize = Marshal.SizeOf( _profileInfo );
                    _profileInfo.lpUserName = WindowsIdentity.GetCurrent().Name;
 
                    if ( LoadUserProfile( _impersonationToken, ref _profileInfo ) )
                    {
                         _profileBehaviour = profileBehaviour;
                    }
                    else
                    {
                         throw new Win32Exception( Marshal.GetLastWin32Error() );
                    }
               }
          }
 
          /// <summary>
          /// Reverts the impersonation.
          /// </summary>
          private void UndoImpersonation()
          {
               if ( _impersonationContext != null )
               {
                    Trace.TraceInformation(
                         string.Format(
                         @"[Impersonation] About to undo impersonation." ) );
 
                    try
                    {
                         _impersonationContext.Undo();
                         _impersonationContext = null;
                    }
                    catch ( Exception x )
                    {
                         Trace.TraceError(
                              string.Format(
                              @"[Impersonation] Error undoing impersonation." ),
                              x );
 
                         throw;
                    }
 
                    Trace.TraceInformation(
                         string.Format(
                         @"[Impersonation] Successfully undone impersonation." ) );
               }
 
               // --
 
               if ( _profileBehaviour == ProfileBehaviour.Load )
               {
                    Trace.TraceInformation(
                         string.Format(
                         @"[Impersonation] About to unload user profile." ) );
 
                    try
                    {
                         if ( !UnloadUserProfile( _impersonationToken, _profileInfo.hProfile ) )
                         {
                              throw new Win32Exception( Marshal.GetLastWin32Error() );
                         }
 
                         _profileBehaviour = ProfileBehaviour.DontLoad;
                    }
                    catch ( Exception x )
                    {
                         Trace.TraceError(
                              string.Format(
                              @"[Impersonation] Error unloading user profile." ),
                              x );
 
                         throw;
                    }
               }
 
               if ( _impersonationToken != IntPtr.Zero )
               {
                    CloseHandle( _impersonationToken );
                    _impersonationToken = IntPtr.Zero;
               }
          }
 
          // ------------------------------------------------------------------
          #endregion
 
          #region Private variables.
          // ------------------------------------------------------------------
 
          private WindowsImpersonationContext _impersonationContext;
 
          private ProfileBehaviour _profileBehaviour = ProfileBehaviour.DontLoad;
          private PROFILEINFO _profileInfo;
          private IntPtr _impersonationToken = IntPtr.Zero;
 
          // ------------------------------------------------------------------
          #endregion
     }
 
     /////////////////////////////////////////////////////////////////////////
 
     /// <summary>
     /// How to log in the user.
     /// </summary>
     public enum LoginType
     {
          #region Enum members.
          // ------------------------------------------------------------------
 
          /// <summary>
          /// Interactive. This is the default.
          /// </summary>
          Interactive = 2,
 
          /// <summary>
          ///
          /// </summary>
          Batch = 4,
 
          /// <summary>
          ///
          /// </summary>
          Network = 3,
 
          /// <summary>
          ///
          /// </summary>
          NetworkClearText = 0,
 
          /// <summary>
          ///
          /// </summary>
          Service = 5,
 
          /// <summary>
          ///
          /// </summary>
          Unlock = 7,
 
          /// <summary>
          ///
          /// </summary>
          NewCredentials = 9
 
          // ------------------------------------------------------------------
          #endregion
     }
 
     /////////////////////////////////////////////////////////////////////////
 
     /// <summary>
     /// How to deal with the user's profile.
     /// </summary>
     /// <remarks>
     /// 2008-05-21, suggested and implemented by Tim Daplyn
     /// (TDaplyn@MedcomSoft.com).
     /// </remarks>
     public enum ProfileBehaviour
     {
          #region Enum members.
          // ------------------------------------------------------------------
 
          /// <summary>
          /// Do not load the user's profile. This is the default behaviour.
          /// </summary>
          DontLoad,
 
          /// <summary>
          /// Load the user's profile.
          /// </summary>
          Load
 
          // ------------------------------------------------------------------
          #endregion
     }
 
     /////////////////////////////////////////////////////////////////////////
}
GeneralSimple, to the point, elegant PinmemberMike Devenney4:31 20 May '08  
GeneralTo log onto another DOMAIN use change as others have shown. PinmemberToddJunk8:51 13 May '08  
GeneralRe: To log onto another DOMAIN use change as others have shown. PinmemberMember 32492803:01 19 Jun '08  
QuestionWhat about GINA Pinmemberthanatoster22:18 5 May '08  
GeneralExcellent Pinmemberffowler10:34 24 Apr '08  
GeneralWonderful Pinmemberdapoussin6:20 7 Apr '08  
GeneralGreat work Pinmemberm.conta5:33 7 Apr '08  
Generalnot working for (remote) file operations Pinmembertomtom19802:40 26 Mar '08  
GeneralRe: not working for (remote) file operations Pinmembertomtom198021:50 26 Mar '08  
GeneralRe: not working for (remote) file operations PinsitebuilderUwe Keim21:56 26 Mar '08  
GeneralRe: not working for (remote) file operations Pinmembertomtom19803:09 27 Mar '08  
GeneralRe: not working for (remote) file operations Pinmemberstancrm22:58 4 Dec '08  
GeneralDoes not work for remote local accounts [modified] PinmemberJonnystar12:46 13 Mar '08  
GeneralRe: Does not work for remote local accounts PinsitebuilderUwe Keim19:01 13 Mar '08  
GeneralRe: Does not work for remote local accounts PinmemberD Waterworth13:36 29 May '08  
QuestionRe: Does not work for remote local accounts PinmemberA_Mano9:39 28 Jul '08  
GeneralGetting invalid logon [modified] Pinmemberdeerinb10:26 23 Jan '08  
GeneralUnfortunately doesn't work in asp.net Pinmembervytas z.1:35 12 Dec '07  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web02 | 2.5.120529.1 | Last Updated 11 Apr 2005
Article Copyright 2005 by Uwe Keim
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid