private readonly bool isLoaded; // is the credential blob loaded #region -- Ctor/Dtor ---------------------------------------------------------- /// <summary></summary> /// <param name="target"></param> /// <param name="realm"></param> /// <param name="showErrorMessage">The user will be informed of the type of error.</param> public PpsClientLogin(string target, string realm, bool showErrorMessage) { this.target = target; this.realm = realm; this.showErrorMessage = showErrorMessage; if (NativeMethods.CredRead(target, NativeMethods.CredentialType.Generic, 0, out var pCred)) { credential = Marshal.PtrToStructure <NativeMethods.CREDENTIAL>(pCred); if (credential.CredentialBlob != IntPtr.Zero) // copy the password in our one memory area { password = Marshal.AllocCoTaskMem(credential.CredentialBlobSize); passwordLength = (credential.CredentialBlobSize >> 1) - 1; UnsafeNativeMethods.CopyMemory(password, credential.CredentialBlob, credential.CredentialBlobSize); } NativeMethods.CredFree(pCred); isLoaded = true; saveOptions = passwordLength > 0 ? PpsClientLoginSaveOptions.Password : PpsClientLoginSaveOptions.UserName; } else { isLoaded = false; saveOptions = PpsClientLoginSaveOptions.None; } } // ctor
} // proc Commit #endregion #region -- ShowWindowsLogin --------------------------------------------------- /// <summary>Show the default windows login dialog.</summary> /// <param name="hwndParent"></param> /// <returns></returns> public bool ShowWindowsLogin(IntPtr hwndParent) { int hr; var dwAuthPackage = (uint)0; var inCredBuffer = IntPtr.Zero; var inCredBufferSize = 0; var outCredBuffer = IntPtr.Zero; var outCredBufferSize = 0; var newPasswordLength = NativeMethods.CREDUI_MAX_PASSWORD_LENGTH; var newPassword = Marshal.AllocCoTaskMem(newPasswordLength); try { // pack the arguments if (isLoaded) { var emptyPasswordSet = false; var emptyPassword = IntPtr.Zero; try { if (password == IntPtr.Zero) { emptyPassword = Marshal.AllocCoTaskMem(2); UnsafeNativeMethods.ZeroMemory(emptyPassword, 2); password = emptyPassword; emptyPasswordSet = true; } if (!NativeMethods.CredPackAuthenticationBuffer(4 /*CRED_PACK_GENERIC_CREDENTIALS*/, credential.UserName, password, inCredBuffer, ref inCredBufferSize)) { hr = Marshal.GetLastWin32Error(); if (hr == 122) { inCredBuffer = Marshal.AllocCoTaskMem((int)inCredBufferSize); if (!NativeMethods.CredPackAuthenticationBuffer(4, credential.UserName, password, inCredBuffer, ref inCredBufferSize)) { throw new Win32Exception(); } } else { throw new Win32Exception(hr); } } } finally { if (emptyPasswordSet) { password = IntPtr.Zero; Marshal.FreeCoTaskMem(emptyPassword); } } } // properties of the dialog var authentifactionError = showErrorMessage ? 1326 /* LogonFailure */ : 0; var messageText = target; if (messageText != null) { var pos = messageText.IndexOf(':'); if (pos != -1) { messageText = messageText.Substring(pos + 1); } } var info = new NativeMethods.CREDUI_INFO { cbSize = Marshal.SizeOf(typeof(NativeMethods.CREDUI_INFO)), hwndParent = hwndParent, pszMessageText = String.Format("{0} ({1}).", messageText, realm), pszCaptionText = "Anmeldung", hbmBanner = IntPtr.Zero }; // show the dialog var flags = NativeMethods.CredUIFlags.Generic | NativeMethods.CredUIFlags.CheckBox; var doSave = saveOptions != PpsClientLoginSaveOptions.None; hr = NativeMethods.CredUIPromptForWindowsCredentials(ref info, authentifactionError, ref dwAuthPackage, inCredBuffer, inCredBufferSize, out outCredBuffer, out outCredBufferSize, ref doSave, flags); if (hr != 0) { if (hr == 1223) // ERROR_CANCELLED { return(false); } else { throw new Win32Exception(hr); } } saveOptions = doSave ? PpsClientLoginSaveOptions.Password : PpsClientLoginSaveOptions.None; // unpack the result var userName = new StringBuilder(NativeMethods.CREDUI_MAX_USERNAME_LENGTH); var domainName = new StringBuilder(NativeMethods.CREDUI_MAX_USERNAME_LENGTH); var userNameLength = userName.Capacity; var domainNameLength = domainName.Capacity; if (!NativeMethods.CredUnPackAuthenticationBuffer(0, outCredBuffer, outCredBufferSize, userName, ref userNameLength, domainName, ref domainNameLength, newPassword, ref newPasswordLength)) { throw new Win32Exception(); } // set the user name if (domainName.Length > 0) { credential.UserName = domainName.ToString() + "\\" + userName.ToString(); } else { credential.UserName = userName.ToString(); } // release the old password var oldPassword = password; var oldPasswordLength = passwordLength; if (newPasswordLength <= 1) { password = IntPtr.Zero; passwordLength = 0; } else { password = newPassword; passwordLength = newPasswordLength - 1; } // set the new one newPassword = oldPassword; newPasswordLength = oldPasswordLength; return(true); } finally { SecureFreeCoTaskMem(ref newPassword, newPasswordLength); SecureFreeCoTaskMem(ref inCredBuffer, inCredBufferSize); SecureFreeCoTaskMem(ref outCredBuffer, outCredBufferSize); } } // func ShowWindowsLogin