title: Impersonation doesn't work with cross domain when using windows authentication
body: <p>I am unable to connect to SQL Server from Application Server, when SQL and App servers exist in different domains, even after using Impersonation.</p>
  
  <p>Our Application (Windows Service) runs as account "acc1" that exists in domain "MyDomain1" and needs to connect to a SQL Server that exists in domain "MyDomain2". Since "acc1" doesn't have access to SQL Server, we are impersonating "acc2" to connect using Windows Authentication. This works perfectly when the App and SQL servers exist in the same domain. </p>
  
  <p>But when the App and SQL servers exist in different domains, we are getting the following error: "Login failed. The login is from an untrusted domain and cannot be used with Windows authentication".</p>
  
  <p>Mixed mode authentication cannot be enabled in SQL Server due to security restrictions. Only windows authentication can be used.</p>
  
  <p>Can someone help with this?</p>
  
  <pre><code>safeTokenHandle = ImpersonationHelper.GetSafeTokenHandle("MyDomain2","acc2","Password2");
  newId = new WindowsIdentity(safeTokenHandle.DangerousGetHandle());
  impersonatedUser = newId.Impersonate();
  </code></pre>
  
  <p>And ImpersonationHelper class as below</p>
  
  <pre><code>using Microsoft.Win32.SafeHandles;
  using System;
  using System.Runtime.ConstrainedExecution;
  using System.Runtime.InteropServices;
  using System.Security;
  using System.Security.Permissions;
  
  namespace Impersonation.Helpers
  {
  public class ImpersonationHelper
  {
      public static object MessageBox { get; private set; }
  
      [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
      public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
          int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);
  
      [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
      public extern static bool CloseHandle(IntPtr handle);
  
      [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
      public static SafeTokenHandle GetSafeTokenHandle(string domainName, string userName, string password)
      {
          SafeTokenHandle safeTokenHandle;
          try
          {
  
              bool returnValue = LogonUser(userName, domainName, password,
                  (int)LogonType.NewCredentials, (int)LogonProvider.WinNT50,
                  out safeTokenHandle);
  
              if (false == returnValue)
              {
                  int ret = Marshal.GetLastWin32Error();
                  Console.WriteLine(string.Format("LogonUser failed with error code : {0}", ret));
                  throw new System.ComponentModel.Win32Exception(ret);
              }
  
              return safeTokenHandle;
          }
          catch (Exception ex)
          {
              throw ex;
          }
      }
  }
  
  public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
  {
      private SafeTokenHandle() : base(true) { }
  
      [DllImport("kernel32.dll")]
      [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
      [SuppressUnmanagedCodeSecurity]
      [return: MarshalAs(UnmanagedType.Bool)]
      private static extern bool CloseHandle(IntPtr handle);
  
      protected override bool ReleaseHandle()
      {
          return CloseHandle(handle);
      }
  }
  
  public enum LogonType
  {
      Interactive = 2,
      Network = 3,
      Batch = 4,
      Service = 5,
      Unlock = 7,
      NetworkClearText = 8,
      NewCredentials = 9,
  }
  
  public enum LogonProvider
  {
      Default = 0,
      WinNT35 = 1,
      WinNT40 = 2,
      WinNT50 = 3
  }
  }
  </code></pre>