title: Impersonating a Windows user
body: <p>I am using the code to impersonate a user account to get access to a file share.</p>
  
  <pre><code>public class Impersonator :
      IDisposable
  {
      #region Public methods.
      // ------------------------------------------------------------------
  
      /// &lt;summary&gt;
      /// Constructor. Starts the impersonation with the given credentials.
      /// Please note that the account that instantiates the Impersonator class
      /// needs to have the 'Act as part of operating system' privilege set.
      /// &lt;/summary&gt;
      /// &lt;param name="userName"&gt;The name of the user to act as.&lt;/param&gt;
      /// &lt;param name="domainName"&gt;The domain name of the user to act as.&lt;/param&gt;
      /// &lt;param name="password"&gt;The password of the user to act as.&lt;/param&gt;
      public Impersonator(
          string userName,
          string domainName,
          string password )
      {
          ImpersonateValidUser( userName, domainName, password );
      }
  
      // ------------------------------------------------------------------
      #endregion
  
      #region IDisposable member.
      // ------------------------------------------------------------------
  
      public void Dispose()
      {
          UndoImpersonation();
      }
  
      // ------------------------------------------------------------------
      #endregion
  
      #region P/Invoke.
      // ------------------------------------------------------------------
  
      [DllImport("advapi32.dll", SetLastError=true)]
      private static extern int LogonUser(
          string lpszUserName,
          string lpszDomain,
          string lpszPassword,
          int dwLogonType,
          int dwLogonProvider,
          ref IntPtr phToken);
  
      [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
      private static extern int DuplicateToken(
          IntPtr hToken,
          int impersonationLevel,
          ref IntPtr hNewToken);
  
      [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
      private static extern bool RevertToSelf();
  
      [DllImport("kernel32.dll", CharSet=CharSet.Auto)]
      private static extern  bool CloseHandle(
          IntPtr handle);
  
      private const int LOGON32_LOGON_INTERACTIVE = 2;
      private const int LOGON32_PROVIDER_DEFAULT = 0;
  
      // ------------------------------------------------------------------
      #endregion
  
      #region Private member.
      // ------------------------------------------------------------------
  
      /// &lt;summary&gt;
      /// Does the actual impersonation.
      /// &lt;/summary&gt;
      /// &lt;param name="userName"&gt;The name of the user to act as.&lt;/param&gt;
      /// &lt;param name="domainName"&gt;The domain name of the user to act as.&lt;/param&gt;
      /// &lt;param name="password"&gt;The password of the user to act as.&lt;/param&gt;
      private void ImpersonateValidUser(
          string userName, 
          string domain, 
          string password )
      {
          WindowsIdentity tempWindowsIdentity = null;
          IntPtr token = IntPtr.Zero;
          IntPtr tokenDuplicate = IntPtr.Zero;
  
          try
          {
              if ( RevertToSelf() )
              {
                  if ( LogonUser(
                      userName, 
                      domain, 
                      password, 
                      LOGON32_LOGON_INTERACTIVE,
                      LOGON32_PROVIDER_DEFAULT, 
                      ref token ) != 0 )
                  {
                      if ( DuplicateToken( token, 2, ref tokenDuplicate ) != 0 )
                      {
                          tempWindowsIdentity = new WindowsIdentity( tokenDuplicate );
                          impersonationContext = tempWindowsIdentity.Impersonate();
                      }
                      else
                      {
                          throw new Win32Exception( Marshal.GetLastWin32Error() );
                      }
                  }
                  else
                  {
                      throw new Win32Exception( Marshal.GetLastWin32Error() );
                  }
              }
              else
              {
                  throw new Win32Exception( Marshal.GetLastWin32Error() );
              }
          }
          finally
          {
              if ( token!= IntPtr.Zero )
              {
                  CloseHandle( token );
              }
              if ( tokenDuplicate!=IntPtr.Zero )
              {
                  CloseHandle( tokenDuplicate );
              }
          }
      }
  
      /// &lt;summary&gt;
      /// Reverts the impersonation.
      /// &lt;/summary&gt;
      private void UndoImpersonation()
      {
          if ( impersonationContext!=null )
          {
              impersonationContext.Undo();
          }   
      }
  
      private WindowsImpersonationContext impersonationContext = null;
  
      // ------------------------------------------------------------------
      #endregion
  }
  </code></pre>
  
  <p>Then using:</p>
  
  <pre><code>using (new Impersonator("username", "domain", "password"))
          {
              Process.Start("explorer.exe", @"/root,\\server01-Prod\abc");
          }
  </code></pre>
  
  <p>I get an "Access Denied" error.</p>
  
  <p>This user supposely has access to this share. I can map a drive, use "net use" but this code will not work. Now I am thinking it is the code. Does anyone see anything? Is there a better way of doing this?</p>