private static bool PromptForCredentials(Uri targetUri, out string username, out string password)
        {
            NativeMethods.CredentialUiInfo credUiInfo = new NativeMethods.CredentialUiInfo
            {
                BannerArt = IntPtr.Zero,
                CaptionText = Title,
                MessageText = String.Format("Enter you credentials for {0}://{1}.", targetUri.Scheme, targetUri.DnsSafeHost),
                Parent = IntPtr.Zero,
                Size = Marshal.SizeOf(typeof(NativeMethods.CredentialUiInfo))
            };

            bool saveCredentials = false;
            NativeMethods.CredentialPackFlags authPackage  = NativeMethods.CredentialPackFlags.None;
            IntPtr packedAuthBufferPtr = IntPtr.Zero;
            uint packedAuthBufferSize = 0;
            NativeMethods.CredentialUiWindowsFlags flags = NativeMethods.CredentialUiWindowsFlags.Generic;

            try
            {
                int result;
                if ((result = NativeMethods.CredUIPromptForWindowsCredentials(ref credUiInfo,
                                                                              0,
                                                                              ref authPackage,
                                                                              IntPtr.Zero,
                                                                              0,
                                                                              out packedAuthBufferPtr,
                                                                              out packedAuthBufferSize,
                                                                              ref saveCredentials,
                                                                              flags)) != NativeMethods.Win32Error.Success)
                {
                    username = null;
                    password = null;

                    return false;
                }

                StringBuilder usernameBuffer = new StringBuilder(512);
                StringBuilder domainBuffer = new StringBuilder(256);
                StringBuilder passwordBuffer = new StringBuilder(512);
                int usernameLen = usernameBuffer.Capacity;
                int passwordLen = passwordBuffer.Capacity;
                int domainLen = domainBuffer.Capacity;

                if (!NativeMethods.CredUnPackAuthenticationBuffer(authPackage,
                                                                  packedAuthBufferPtr,
                                                                  packedAuthBufferSize,
                                                                  usernameBuffer,
                                                                  ref usernameLen,
                                                                  domainBuffer,
                                                                  ref domainLen,
                                                                  passwordBuffer,
                                                                  ref passwordLen))
                {
                    username = null;
                    password = null;

                    return false;
                }

                username = usernameBuffer.ToString();
                password = passwordBuffer.ToString();

                return true;
            }
            catch { throw; }
            finally
            {
                if (packedAuthBufferPtr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(packedAuthBufferPtr);
                }
            }
        }
        private static bool ModalPromptForCredentials(Uri targetUri, string message, out string username, out string password)
        {
            Debug.Assert(targetUri != null);
            Debug.Assert(message != null);

            Trace.WriteLine("Program::ModalPromptForCredemtials");

            NativeMethods.CredentialUiInfo credUiInfo = new NativeMethods.CredentialUiInfo
            {
                BannerArt = IntPtr.Zero,
                CaptionText = Title,
                MessageText = message,
                Parent = IntPtr.Zero,
                Size = Marshal.SizeOf(typeof(NativeMethods.CredentialUiInfo))
            };
            NativeMethods.CredentialUiWindowsFlags flags = NativeMethods.CredentialUiWindowsFlags.Generic;
            NativeMethods.CredentialPackFlags authPackage = NativeMethods.CredentialPackFlags.None;
            IntPtr packedAuthBufferPtr = IntPtr.Zero;
            IntPtr inBufferPtr = IntPtr.Zero;
            uint packedAuthBufferSize = 0;
            bool saveCredentials = false;
            int inBufferSize = 0;

            return ModalPromptDisplayDialog(ref credUiInfo,
                                            ref authPackage,
                                            packedAuthBufferPtr,
                                            packedAuthBufferSize,
                                            inBufferPtr,
                                            inBufferSize,
                                            saveCredentials,
                                            flags,
                                            out username,
                                            out password);
        }
        private static bool ModalPromptForPassword(Uri targetUri, string message, string username, out string password)
        {
            Debug.Assert(targetUri != null);
            Debug.Assert(message != null);
            Debug.Assert(username != null);

            Trace.WriteLine("Program::ModalPromptForPassword");

            NativeMethods.CredentialUiInfo credUiInfo = new NativeMethods.CredentialUiInfo
            {
                BannerArt = IntPtr.Zero,
                CaptionText = Title,
                MessageText = message,
                Parent = IntPtr.Zero,
                Size = Marshal.SizeOf(typeof(NativeMethods.CredentialUiInfo))
            };
            NativeMethods.CredentialUiWindowsFlags flags = NativeMethods.CredentialUiWindowsFlags.Generic;
            NativeMethods.CredentialPackFlags authPackage = NativeMethods.CredentialPackFlags.None;
            IntPtr packedAuthBufferPtr = IntPtr.Zero;
            IntPtr inBufferPtr = IntPtr.Zero;
            uint packedAuthBufferSize = 0;
            bool saveCredentials = false;
            int inBufferSize = 0;

            try
            {
                int error;

                // execute with `null` to determine buffer size
                // always returns false when determining size, only fail if `inBufferSize` looks bad
                NativeMethods.CredPackAuthenticationBuffer(flags: authPackage,
                                                           username: username,
                                                           password: String.Empty,
                                                           packedCredentials: inBufferPtr,
                                                           packedCredentialsSize: ref inBufferSize);
                if (inBufferSize <= 0)
                {
                    error = Marshal.GetLastWin32Error();
                    Trace.WriteLine("   unable to determine credential buffer size (" + NativeMethods.Win32Error.GetText(error) + ").");

                    username = null;
                    password = null;

                    return false;
                }

                inBufferPtr = Marshal.AllocHGlobal(inBufferSize);

                if (!NativeMethods.CredPackAuthenticationBuffer(flags: authPackage,
                                                                username: username,
                                                                password: String.Empty,
                                                                packedCredentials: inBufferPtr,
                                                                packedCredentialsSize: ref inBufferSize))
                {
                    error = Marshal.GetLastWin32Error();
                    Trace.WriteLine("   unable to write to credential buffer (" + NativeMethods.Win32Error.GetText(error) + ").");

                    username = null;
                    password = null;

                    return false;
                }

                return ModalPromptDisplayDialog(ref credUiInfo,
                                                ref authPackage,
                                                packedAuthBufferPtr,
                                                packedAuthBufferSize,
                                                inBufferPtr,
                                                inBufferSize,
                                                saveCredentials,
                                                flags,
                                                out username,
                                                out password);
            }
            finally
            {
                if (inBufferPtr != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(inBufferPtr);
                }
            }
        }
        private static bool PromptForCredentialsBase( Uri targetUri, out string username, out string password, string message, string displayUsername = "") {
            Debug.Assert(targetUri != null);

            Trace.WriteLine("Program::PromptForCredentials");

            NativeMethods.CredentialUiInfo credUiInfo = new NativeMethods.CredentialUiInfo
            {
                BannerArt = IntPtr.Zero,
                CaptionText = Title,
                MessageText = message,
                Parent = IntPtr.Zero,
                Size = Marshal.SizeOf(typeof(NativeMethods.CredentialUiInfo))
            };

            bool saveCredentials = false;
            NativeMethods.CredentialPackFlags authPackage = NativeMethods.CredentialPackFlags.None;

            IntPtr inBufferPtr = IntPtr.Zero;
            int inBufferSize = 0;

            if ( !string.IsNullOrEmpty( displayUsername ) ) {
                // Execute with ZeroPtr to determine buffer size
                NativeMethods.CredPackAuthenticationBuffer( authPackage, displayUsername, "", inBufferPtr, ref inBufferSize );
                inBufferPtr = Marshal.AllocCoTaskMem( inBufferSize );
                NativeMethods.CredPackAuthenticationBuffer( authPackage, displayUsername, "", inBufferPtr, ref inBufferSize );
            }

            IntPtr packedAuthBufferPtr = IntPtr.Zero;
            uint packedAuthBufferSize = 0;
            NativeMethods.CredentialUiWindowsFlags flags = NativeMethods.CredentialUiWindowsFlags.Generic;

            try
            {
                // open a standard Windows authentication dialog to acquire username + password credentials
                int error;
                if ((error = NativeMethods.CredUIPromptForWindowsCredentials(ref credUiInfo,
                                                                              0,
                                                                              ref authPackage,
                                                                              inBufferPtr,
                                                                              (uint)inBufferSize,
                                                                              out packedAuthBufferPtr,
                                                                              out packedAuthBufferSize,
                                                                              ref saveCredentials,
                                                                              flags)) != NativeMethods.Win32Error.Success)
                {
                    username = null;
                    password = null;

                    Trace.WriteLine("   credential prompt failed (" + NativeMethods.Win32Error.GetText(error) + ").");

                    return false;
                }

                // use `StringBuilder` references instead of string so that they can be written to
                StringBuilder usernameBuffer = new StringBuilder(512);
                StringBuilder domainBuffer = new StringBuilder(256);
                StringBuilder passwordBuffer = new StringBuilder(512);
                int usernameLen = usernameBuffer.Capacity;
                int passwordLen = passwordBuffer.Capacity;
                int domainLen = domainBuffer.Capacity;

                // unpack the result into locally useful data
                if (!NativeMethods.CredUnPackAuthenticationBuffer(authPackage,
                                                                  packedAuthBufferPtr,
                                                                  packedAuthBufferSize,
                                                                  usernameBuffer,
                                                                  ref usernameLen,
                                                                  domainBuffer,
                                                                  ref domainLen,
                                                                  passwordBuffer,
                                                                  ref passwordLen))
                {
                    username = null;
                    password = null;

                    error = Marshal.GetLastWin32Error();
                    Trace.WriteLine("   failed to unpack buffer (" + NativeMethods.Win32Error.GetText(error) + ").");

                    return false;
                }

                username = usernameBuffer.ToString();
                password = passwordBuffer.ToString();

                return true;
            }
            catch { throw; }
            finally
            {
                if (packedAuthBufferPtr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(packedAuthBufferPtr);
                }

                if (inBufferPtr != IntPtr.Zero) 
                {
                    Marshal.FreeCoTaskMem( inBufferPtr );
                }
            }
        }