Search code examples
c#pinvoke

Show Authentication dialog in C# for windows Vista/7


I want to get network login credentials from a user.

I'm using .NET 3.5 with C#. Up until now I used the CredUIPromptForCredentials call (a very useful link on how to use it can be found here)

My problem is that the CredUIPromptForCredentials API call shows the old windows 2000/XP credentials dialog and not the new Vista/7 one.

I've read on msdn that I should use the CredUIPromptForWindowsCredentials function.

Can someone post an example of how to use it with C#? I also need to be able to get the credentials that were entered.


Solution

  • 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.