The code in the following class was adapted from the code in 
http://msdn2.microsoft.com/en-us/librar ... text(VS.71).aspx.
If you incorporate this code into a DLL, be sure to demand FullTrust.
public class WindowsImpersonation
{
    [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
    public static WindowsIdentity GetWindowsIdentity(string domainName, string userName, string password)
    {
        IntPtr tokenHandle = IntPtr.Zero;
        IntPtr dupeTokenHandle = IntPtr.Zero;
        try
        {
            const int SecurityImpersonation = 2;
            tokenHandle = IntPtr.Zero;
            dupeTokenHandle = IntPtr.Zero;
            if (!LogonUser(userName, domainName, password, (int)LogonSessionType.Interactive, (int)LogonProvider.Default, ref tokenHandle))
                throw new ImpersonationException("Could not log on user {0}\\{1} (LogonUser).  Error was {2}",
                    domainName, userName, GetErrorMessage(Marshal.GetLastWin32Error()));
            if (!DuplicateToken(tokenHandle, SecurityImpersonation, ref dupeTokenHandle))
                throw new ImpersonationException("Could not log on user {0}\\{1} (DuplicateToken).  Error was {2}",
                    domainName, userName, GetErrorMessage(Marshal.GetLastWin32Error()));
            // The token that is passed to the following constructor must 
            // be a primary token in order to use it for impersonation.
            return new WindowsIdentity(dupeTokenHandle);
        }
        catch (Exception ex)
        {
            throw new ImpersonationException(ex, "Error while authenticating user {0}\\{1}", domainName, userName);
        }
        finally
        {
            if (tokenHandle != IntPtr.Zero)
                CloseHandle(tokenHandle);
            if (dupeTokenHandle != IntPtr.Zero)
                CloseHandle(dupeTokenHandle);
        }
    }
    private enum LogonSessionType : uint
    {
        Interactive = 2,
        Network,
        Batch,
        Service,
        Proxy,
        Unlock,
        NetworkCleartext,
        NewCredentials,
        RemoteInteractive,
        CachedInteractive,
        CachedRemoteInteractive,
        CachedUnlock
    }
    private enum LogonProvider : uint
    {
        Default = 0, // default for platform (use this!)
        WinNT35,     // sends smoke signals to authority
        WinNT40,     // uses NTLM
        WinNT50      // negotiates Kerb or NTLM
    }
    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
        int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
    [DllImport("kernel32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
    private unsafe static extern int FormatMessage(int dwFlags, ref IntPtr lpSource,
        int dwMessageId, int dwLanguageId, ref String lpBuffer, int nSize, IntPtr* Arguments);
    [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);
    // GetErrorMessage formats and returns an error message
    // corresponding to the input errorCode.
    private unsafe static string GetErrorMessage(int errorCode)
    {
        int FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100;
        int FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
        int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
        //int errorCode = 0x5; //ERROR_ACCESS_DENIED
        //throw new System.ComponentModel.Win32Exception(errorCode);
        int messageSize = 255;
        String lpMsgBuf = "";
        int dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
        IntPtr ptrlpSource = IntPtr.Zero;
        IntPtr prtArguments = IntPtr.Zero;
        int retVal = FormatMessage(dwFlags, ref ptrlpSource, errorCode, 0, ref lpMsgBuf, messageSize, &prtArguments);
        if (0 == retVal)
        {
            throw new Exception("Failed to format message for error code " + errorCode + ". ");
        }
        return lpMsgBuf;
    }
}
public class ImpersonationException : Exception
{
    public ImpersonationException(Exception innerException, string message, params object[] args)
        : base(string.Format(message, args), innerException)
    {
    }
    public ImpersonationException(string message, params object[] args)
        : this(null, message, args)
    {
    }
}