Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Net;
- using System.Runtime.InteropServices;
- using System.Text;
- namespace SMM.Helper
- {
- public static class CredentialsUI
- {
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- private struct CREDUI_INFO
- {
- public int cbSize;
- public IntPtr hwndParent;
- public string pszMessageText;
- public string pszCaptionText;
- public IntPtr hbmBanner;
- }
- [Flags]
- private enum PromptForWindowsCredentialsFlags
- {
- /// <summary>
- /// The caller is requesting that the credential provider return the user name and password in plain text.
- /// This value cannot be combined with SECURE_PROMPT.
- /// </summary>
- CREDUIWIN_GENERIC = 0x1,
- /// <summary>
- /// The Save check box is displayed in the dialog box.
- /// </summary>
- CREDUIWIN_CHECKBOX = 0x2,
- /// <summary>
- /// Only credential providers that support the authentication package specified by the authPackage parameter should be enumerated.
- /// This value cannot be combined with CREDUIWIN_IN_CRED_ONLY.
- /// </summary>
- CREDUIWIN_AUTHPACKAGE_ONLY = 0x10,
- /// <summary>
- /// Only the credentials specified by the InAuthBuffer parameter for the authentication package specified by the authPackage parameter should be enumerated.
- /// If this flag is set, and the InAuthBuffer parameter is NULL, the function fails.
- /// This value cannot be combined with CREDUIWIN_AUTHPACKAGE_ONLY.
- /// </summary>
- CREDUIWIN_IN_CRED_ONLY = 0x20,
- /// <summary>
- /// Credential providers should enumerate only administrators. This value is intended for User Account Control (UAC) purposes only. We recommend that external callers not set this flag.
- /// </summary>
- CREDUIWIN_ENUMERATE_ADMINS = 0x100,
- /// <summary>
- /// Only the incoming credentials for the authentication package specified by the authPackage parameter should be enumerated.
- /// </summary>
- CREDUIWIN_ENUMERATE_CURRENT_USER = 0x200,
- /// <summary>
- /// The credential dialog box should be displayed on the secure desktop. This value cannot be combined with CREDUIWIN_GENERIC.
- /// Windows Vista: This value is not supported until Windows Vista with SP1.
- /// </summary>
- CREDUIWIN_SECURE_PROMPT = 0x1000,
- /// <summary>
- /// The credential provider should align the credential BLOB pointed to by the refOutAuthBuffer parameter to a 32-bit boundary, even if the provider is running on a 64-bit system.
- /// </summary>
- CREDUIWIN_PACK_32_WOW = 0x10000000,
- }
- [DllImport("ole32.dll")]
- private static extern void CoTaskMemFree(IntPtr ptr);
- [DllImport("credui.dll", CharSet = CharSet.Unicode, SetLastError = true)]
- private static extern Boolean CredPackAuthenticationBuffer(
- int dwFlags,
- string pszUserName,
- string pszPassword,
- IntPtr pPackedCredentials,
- ref int pcbPackedCredentials);
- [DllImport("credui.dll", CharSet = CharSet.Unicode)]
- private 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,
- PromptForWindowsCredentialsFlags flags);
- [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);
- public static NetworkCredential PromptForCreds(string PromptCaption = "Credentials needed", string PromptMessage = "Please enter your username and password")
- {
- bool save = false;
- int errorcode = 0;
- uint dialogReturn;
- uint authPackage = 0;
- IntPtr outCredBuffer = IntPtr.Zero;
- uint outCredSize;
- try
- {
- CREDUI_INFO credui = new CREDUI_INFO();
- credui.cbSize = Marshal.SizeOf(credui);
- credui.pszCaptionText = PromptCaption;
- credui.pszMessageText = PromptMessage;
- IntPtr hwnd = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle;
- if (hwnd != IntPtr.Zero) credui.hwndParent = hwnd;
- int maxUserName = 256;
- int maxDomain = 100;
- int maxPassword = 127; // Windows 10 max
- var usernameBuf = new StringBuilder(maxUserName);
- var domainBuf = new StringBuilder(maxDomain);
- var passwordBuf = new StringBuilder(maxPassword);
- while (true) //Show the dialog again and again, until Cancel is clicked or the entered credentials are correct.
- {
- //Show the dialog
- dialogReturn = CredUIPromptForWindowsCredentials(ref credui,
- errorcode,
- ref authPackage,
- (IntPtr)0, //You can force that a specific username is shown in the dialog. Create it with 'CredPackAuthenticationBuffer()'. Then, the buffer goes here...
- 0, //...and the size goes here. You also have to add CREDUIWIN_IN_CRED_ONLY to the flags (last argument).
- out outCredBuffer,
- out outCredSize,
- ref save,
- 0); //Use the PromptForWindowsCredentialsFlags-Enum here. You can use multiple flags if you seperate them with | .
- if (dialogReturn != 0) break; //Break, if Cancel was clicked or an error occurred
- /*Unpack your credentials (outCredBuffer, outCredSize) with 'CredUnPackAuthenticationBuffer()'
- For example, it returns a bool 'credentialsEnteredCorrect':*/
- NetworkCredential netCredential;
- if (CredUnPackAuthenticationBuffer(0, outCredBuffer, outCredSize, usernameBuf, ref maxUserName, domainBuf, ref maxDomain, passwordBuf, ref maxPassword))
- {
- //clear the memory allocated by CredUIPromptForWindowsCredentials
- netCredential = new NetworkCredential()
- {
- UserName = usernameBuf.ToString(),
- Password = passwordBuf.ToString(),
- Domain = domainBuf.ToString()
- };
- return netCredential;
- }
- }
- }
- catch (Exception e)
- {
- throw e; // Caller needs to handle this, only here so we can release the buffer in finally
- }
- finally
- {
- if (outCredBuffer != IntPtr.Zero) CoTaskMemFree(outCredBuffer);
- }
- return null;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement