Here is the class that implements IAuthenticationModule and P/Invokes into the native dll created in the previous post.

using System;
using System.IO;
using System.Net;
using System.Data;
using System.Text;
using System.Runtime.InteropServices;

namespace Microsoft.Authentication.NTLM
{
 /// <summary>
 /// Summary description for Class1.
 /// </summary>
 public class NTLMAuth : IAuthenticationModule
 {
  [DllImport("NTLMAuthEx.dll")]
  public static extern IntPtr Initialize(String pszUserID, String pszPassword, String pszDomain);

  [DllImport("NTLMAuthEx.dll")]
  public static extern IntPtr Authenicate(byte[] pszResponse, byte[] pbBuffer, ref IntPtr nBufferSize);

  public NTLMAuth()
  {
  }

  public Authorization Authenticate(string challenge, WebRequest request, ICredentials credentials)
  {
   NetworkCredential nc = (NetworkCredential)credentials;

   IntPtr dwBufferSize = IntPtr.Zero;
   byte[] bChallenge = null;
   bool fAuthFinished = false;

   if (challenge.StartsWith("NTLM"))
   {
    fAuthFinished = true;
    bChallenge =  Encoding.ASCII.GetBytes(challenge.Substring(5));
    dwBufferSize = (IntPtr)1029;
   }
   else
   {
    dwBufferSize = Initialize(nc.UserName, nc.Password, nc.Domain);
   }

   if ((int)dwBufferSize == 0)
   {
    throw new Exception("NTLM Authenticate Error: Could not allocate buffer");
   }

   byte[] bBuffer = new byte[(int)dwBufferSize];
   IntPtr dwReturn = Authenicate(bChallenge, bBuffer, ref dwBufferSize);

   if ((int)dwReturn != 0)
   {
    throw new Exception(String.Format("NTLM Authenticate Error: {0}", dwReturn));
   }

   string sToken = "NTLM " +  Encoding.ASCII.GetString(bBuffer, 0, (int)dwBufferSize);

   return new Authorization(sToken, fAuthFinished);
  }

  public Authorization PreAuthenticate(WebRequest request, ICredentials credentials)
  {
   return Authenticate("NTLM", request, credentials);
  }

  public string AuthenticationType
  {
   get
   {
    return "NTLM";
   }
  }

  public bool CanPreAuthenticate
  {
   get
   {
    return true;
   }
  }
 }
}