title: What is the magic to Windows impersonation with LOGON32_LOGON_NEW_CREDENTIALS?
body: <p>From my reading on user impersonation on Windows, one should properly use the LOGON32_LOGON_NEW_CREDENTIALS logon type for impersonating a user to a database. Using Matt Johnson's nice impersonation wrapper (originally posted <a href="https://stackoverflow.com/a/7250145/115690">here</a> and then polished up <a href="https://github.com/mj1856/SimpleImpersonation" rel="nofollow noreferrer">here</a>), I tried to test this out--here is my entire program except for constants defining my particular DOMAIN, USER, PWD, and CONN_STRING.</p>
  
  <pre><code>using System;
  using System.Data.SqlClient;
  using SimpleImpersonation;
  
  namespace ImpersonationDemo
  {
      class Program
      {
          private static SqlConnection _connection;
  
          static void Main(string[] args)
          {
              using (Impersonation.LogonUser(
                      DOMAIN, USER, PWD, LogonType.NewCredentials))
              {
                  GetOpenConnection();
                  CheckDbCredentials();
                  CloseConnection();
              }
              Console.WriteLine("Press return to exit");
              Console.ReadLine();
          }
  
          private static void CheckDbCredentials()
          {
              using (
                  var command = new SqlCommand(
                      "SELECT nt_user_name, SUSER_SNAME() "
                      +"FROM sys.dm_exec_sessions WHERE session_id = @@SPID",
                      _connection))
              {
                  using (SqlDataReader reader = command.ExecuteReader())
                  {
                      while (reader.Read())
                      {
                          Console.WriteLine("{0}, {1}",
                              reader.GetString(0), reader.GetString(1));
                      }
                  }
              }
          }
  
  
          private static void GetOpenConnection()
          {
              _connection = new SqlConnection(CONN_STRING);
              _connection.Open();
          }
  
          private static void CloseConnection()
          {
              _connection.Close();
          }
      }
  }
  </code></pre>
  
  <p><strong>But that does not work.</strong> The output reports <strong>me</strong> (my underlying logged in user) from both <code>nt_user_name</code> and <code>SUSER_NAME()</code>. (And SQL Profiler reports exactly the same thing; the query in code is simply a convenient way to see what SQL Profiler tells me.)</p>
  
  <p>If I change from <code>LogonType.NewCredentials</code> to <code>LogonType.Interactive</code> (these enums have the values you would expect, as defined on <a href="http://pinvoke.net/default.aspx/advapi32.LogonUser" rel="nofollow noreferrer">pinvoke.net</a>), then it does work--the above code reports the correct DOMAIN and USER impersonation. But this also means the current session is being impersonated which I do not want--I only want the DB connection to be impersonated.</p>
  
  <p>I thought I found one glitch in the above--Johnson's Impersonation wrapper hard-codes the logon provider as <code>LOGON32_PROVIDER_DEFAULT</code>, when the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa378184.aspx" rel="nofollow noreferrer">LogonUser API</a> clearly states that the <code>LOGON32_LOGON_NEW_CREDENTIALS</code> logon type is supported only by the <code>LOGON32_PROVIDER_WINNT50</code> logon provider. So I grabbed the source and added a parameter to allow specifying the requisite logon provider... but that made no difference.</p>
  
  <p>So what am I missing?</p>