Show Authentication dialog in C# for windows Vista/7

I managed to implement a solution that is working for me.

Here is the source code:

    [DllImport("ole32.dll")]
    public static extern void CoTaskMemFree(IntPtr ptr);

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    private struct CREDUI_INFO
    {
        public int cbSize;
        public IntPtr hwndParent;
        public string pszMessageText;
        public string pszCaptionText;
        public IntPtr hbmBanner;
    }  


    [DllImport("credui.dll", CharSet = CharSet.Auto)]
    private static extern bool CredUnPackAuthenticationBuffer(int dwFlags,
                                                               IntPtr pAuthBuffer,
                                                               uint cbAuthBuffer,
                                                               StringBuilder pszUserName,
                                                               ref int pcchMaxUserName,
                                                               StringBuilder pszDomainName,
                                                               ref int pcchMaxDomainame,
                                                               StringBuilder pszPassword,
                                                               ref int pcchMaxPassword);

    [DllImport("credui.dll", CharSet = CharSet.Auto)]
    private static extern int CredUIPromptForWindowsCredentials(ref CREDUI_INFO notUsedHere,
                                                                 int authError,
                                                                 ref uint authPackage,
                                                                 IntPtr InAuthBuffer,
                                                                 uint InAuthBufferSize,
                                                                 out IntPtr refOutAuthBuffer,
                                                                 out uint refOutAuthBufferSize,
                                                                 ref bool fSave,
                                                                 int flags);



    public static void GetCredentialsVistaAndUp(string serverName, out NetworkCredential networkCredential)
    {
        CREDUI_INFO credui = new CREDUI_INFO();
        credui.pszCaptionText = "Please enter the credentails for " + serverName;
        credui.pszMessageText = "DisplayedMessage";
        credui.cbSize = Marshal.SizeOf(credui);
        uint authPackage = 0;
        IntPtr outCredBuffer = new IntPtr();
        uint outCredSize;
        bool save = false;
        int result = CredUIPromptForWindowsCredentials(ref credui,
                                                       0,
                                                       ref authPackage,
                                                       IntPtr.Zero,
                                                       0,
                                                       out outCredBuffer,
                                                       out outCredSize,
                                                       ref save,
                                                       1 /* Generic */);

        var usernameBuf = new StringBuilder(100);
        var passwordBuf  = new StringBuilder(100);
        var domainBuf = new StringBuilder(100);

        int maxUserName = 100;
        int maxDomain = 100;
        int maxPassword = 100;
        if (result == 0)
        {
            if (CredUnPackAuthenticationBuffer(0, outCredBuffer, outCredSize, usernameBuf, ref maxUserName,
                                               domainBuf, ref maxDomain, passwordBuf, ref maxPassword))
            {
                //TODO: ms documentation says we should call this but i can't get it to work
                //SecureZeroMem(outCredBuffer, outCredSize);

                //clear the memory allocated by CredUIPromptForWindowsCredentials 
                CoTaskMemFree(outCredBuffer);
                networkCredential = new NetworkCredential()
                                        {
                                            UserName = usernameBuf.ToString(),
                                            Password = passwordBuf.ToString(),
                                            Domain = domainBuf.ToString()
                                        };
                return;
            }
        }

        networkCredential = null;
    }

I still need to work out the fine details such as how to remember the last credentials that were entered etc...

But the major part works.


Here is some code to go on extracted from bytes.com post:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct _CREDUI_INFO
{
  public int cbSize;
  public IntPtr hwndParent;
  public string pszMessageText;
  public string pszCaptionText;
  public IntPtr hbmBanner;
}
class Program
{
  [DllImport("credui.dll", CharSet=CharSet.Unicode)]
  internal static extern uint CredUIPromptForWindowsCredentials(ref
    _CREDUI_INFO notUsedHere,
    int authError,
    ref uint authPackage,
    IntPtr InAuthBuffer,
    uint InAuthBufferSize,
    out IntPtr refOutAuthBuffer,
    out uint refOutAuthBufferSize,
    ref bool fSave,
    int flags);

  const int CREDUIWIN_AUTHPACKAGE_ONLY = 0x10;

  static void Main()
  {
    _CREDUI_INFO credui = new _CREDUI_INFO();
    credui.cbSize = Marshal.SizeOf(credui);
    credui.pszCaptionText = "Testje";
    credui.pszMessageText = "Message";
    uint authPackage = 0;
    IntPtr outCredBuffer;
    uint outCredSize;
    bool save = false;

    uint ret = CredUIPromptForWindowsCredentials(ref credui,
      0,
      ref authPackage,
      IntPtr.Zero,
      0,
      out outCredBuffer,
      out outCredSize,
      ref save,
      CREDUIWIN_AUTHPACKAGE_ONLY);

    if(ret != 0)
    {
      // failed to load function...
      // ...
    }
    else
    {
      // extract credentials from the buffer returned, using more
      //   credui.dll API's .
      // ...
    }
  }
}

Tags:

C#

Pinvoke