using Microsoft.Win32.SafeHandles;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;

namespace KarleyLibrary
{
    public static class Impersonation
    {
        [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
        int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);

        public static bool Impersonate(string user, string password, string domain, Action action)
        {
            SafeTokenHandle safeTokenHandle;
            bool returnValue = LogonUser(user, domain, password,
                2, 0,
                out safeTokenHandle);

            if (!returnValue)
                return false;

            try
            {
                WindowsIdentity.RunImpersonated(new WindowsIdentity(safeTokenHandle.DangerousGetHandle()).AccessToken, () =>
                {
                    action();
                });
                return true;
            }
            catch (Exception e)
            {
                return false;
            }
        }
        private 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);
            }
        }
    }

    
}
