using System;
using System.Security.Principal;
using System.Runtime.InteropServices;

namespace LumiSoft.Net.FTP.Server
{
	/// <summary>
	/// Impersonate helper.
	/// </summary>
	public class Impersonate
	{
		[DllImport("advapi32.dll", SetLastError=true)]
		private extern static bool LogonUser(string userName,string domainName,string password,int dwLogonType,int dwLogonProvider,ref IntPtr phToken);
    
		[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
		private extern static bool CloseHandle(IntPtr handle);

		[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
		private extern static bool DuplicateToken(IntPtr ExistingTokenHandle,int SECURITY_IMPERSONATION_LEVEL,ref IntPtr DuplicateTokenHandle);

		public static bool LogonAndImpersonateUser(string userName,string password)
		{
			try{
				IntPtr tokenHandle = new IntPtr(0);
				IntPtr dupeTokenHandle = new IntPtr(0);

				const int LOGON32_PROVIDER_DEFAULT = 0;
				//This parameter causes LogonUser to create a primary token.
				const int LOGON32_LOGON_INTERACTIVE = 2;
				const int SecurityImpersonation = 2;

				tokenHandle = IntPtr.Zero;
				dupeTokenHandle = IntPtr.Zero;

				// Call LogonUser to obtain an handle to an access token.
				if(!LogonUser(userName,"",password,LOGON32_LOGON_INTERACTIVE,LOGON32_PROVIDER_DEFAULT,ref tokenHandle)){               
					return false;
				}
	        
				bool retVal = DuplicateToken(tokenHandle, SecurityImpersonation, ref dupeTokenHandle);
				if(!DuplicateToken(tokenHandle, SecurityImpersonation, ref dupeTokenHandle)){
					CloseHandle(tokenHandle);				 		
					return false;
				}


				// The token that is passed to the following constructor must 
				// be a primary token to impersonate.
				WindowsIdentity newId = new WindowsIdentity(tokenHandle);
				WindowsImpersonationContext impersonatedUser = newId.Impersonate();
			}
			catch{
				return false;
			}

			return true;
		}
	}
}
