diff --git a/GreenshotCore/Helpers/CredentialsHelper.cs b/GreenshotCore/Helpers/CredentialsHelper.cs
new file mode 100644
index 000000000..256fd1cc3
--- /dev/null
+++ b/GreenshotCore/Helpers/CredentialsHelper.cs
@@ -0,0 +1,593 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2010 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Drawing;
+using System.Runtime.InteropServices;
+using System.Reflection;
+using System.Text;
+using System.Threading;
+using System.Windows.Forms;
+
+///
+/// The following code comes from: http://www.developerfusion.com/code/4693/using-the-credential-management-api/
+/// and is slightly modified so it works for us.
+/// The following code is an example for a login, it will call the Authenticate with user/password
+/// which should return true if the login worked, false if not.
+/// private static bool Login(string system, string name) {
+/// try {
+/// CredentialsDialog dialog = new CredentialsDialog(system);
+/// dialog.Name = name;
+/// while (dialog.Show(dialog.Name) == DialogResult.OK) {
+/// if (Authenticate(dialog.Name, dialog.Password)) {
+/// if (dialog.SaveChecked) dialog.Confirm(true);
+/// return true;
+/// } else {
+/// try {
+/// dialog.Confirm(false);
+/// } catch (ApplicationException) {
+/// // exception handling ...
+/// }
+/// }
+/// }
+/// } catch (ApplicationException) {
+/// // exception handling ...
+/// }
+/// return false;
+/// }
+///
+namespace Greenshot.Helpers {
+ /// Encapsulates dialog functionality from the Credential Management API.
+ public sealed class CredentialsDialog {
+ /// The only valid bitmap height (in pixels) of a user-defined banner.
+ private const int ValidBannerHeight = 60;
+
+ /// The only valid bitmap width (in pixels) of a user-defined banner.
+ private const int ValidBannerWidth = 320;
+
+ /// Initializes a new instance of the class
+ /// with the specified target.
+ /// The name of the target for the credentials, typically a server name.
+ public CredentialsDialog(string target) : this(target, null) {
+ }
+
+ /// Initializes a new instance of the class
+ /// with the specified target and caption.
+ /// The name of the target for the credentials, typically a server name.
+ /// The caption of the dialog (null will cause a system default title to be used).
+ public CredentialsDialog(string target, string caption) : this(target, caption, null) {
+ }
+
+ /// Initializes a new instance of the class
+ /// with the specified target, caption and message.
+ /// The name of the target for the credentials, typically a server name.
+ /// The caption of the dialog (null will cause a system default title to be used).
+ /// The message of the dialog (null will cause a system default message to be used).
+ public CredentialsDialog(string target, string caption, string message) : this(target, caption, message, null) {
+ }
+
+ /// Initializes a new instance of the class
+ /// with the specified target, caption, message and banner.
+ /// The name of the target for the credentials, typically a server name.
+ /// The caption of the dialog (null will cause a system default title to be used).
+ /// The message of the dialog (null will cause a system default message to be used).
+ /// The image to display on the dialog (null will cause a system default image to be used).
+ public CredentialsDialog(string target, string caption, string message, Image banner) {
+ this.Target = target;
+ this.Caption = caption;
+ this.Message = message;
+ this.Banner = banner;
+ }
+
+ private bool _alwaysDisplay = false;
+ ///
+ /// Gets or sets if the dialog will be shown even if the credentials
+ /// can be returned from an existing credential in the credential manager.
+ ///
+ public bool AlwaysDisplay {
+ get {
+ return _alwaysDisplay;
+ }
+ set {
+ _alwaysDisplay = value;
+ }
+ }
+
+ private bool _excludeCertificates = true;
+ /// Gets or sets if the dialog is populated with name/password only.
+ public bool ExcludeCertificates {
+ get {
+ return _excludeCertificates;
+ }
+ set {
+ _excludeCertificates = value;
+ }
+ }
+
+ private bool _persist = true;
+ /// Gets or sets if the credentials are to be persisted in the credential manager.
+ public bool Persist {
+ get {
+ return _persist;
+ }
+ set {
+ _persist = value;
+ }
+ }
+
+ private bool _keepName = false;
+ /// Gets or sets if the name is read-only.
+ public bool KeepName {
+ get {
+ return _keepName;
+ }
+ set {
+ _keepName = value;
+ }
+ }
+
+ private string _name = String.Empty;
+ /// Gets or sets the name for the credentials.
+ public string Name {
+ get {
+ return _name;
+ }
+ set {
+ if (value != null) {
+ if (value.Length > CREDUI.MAX_USERNAME_LENGTH) {
+ string message = String.Format(
+ Thread.CurrentThread.CurrentUICulture,
+ "The name has a maximum length of {0} characters.",
+ CREDUI.MAX_USERNAME_LENGTH);
+ throw new ArgumentException(message, "Name");
+ }
+ }
+ _name = value;
+ }
+ }
+
+ private string _password = String.Empty;
+ /// Gets or sets the password for the credentials.
+ public string Password {
+ get {
+ return _password;
+ }
+ set {
+ if (value != null) {
+ if (value.Length > CREDUI.MAX_PASSWORD_LENGTH) {
+ string message = String.Format(
+ Thread.CurrentThread.CurrentUICulture,
+ "The password has a maximum length of {0} characters.",
+ CREDUI.MAX_PASSWORD_LENGTH);
+ throw new ArgumentException(message, "Password");
+ }
+ }
+ _password = value;
+ }
+ }
+
+ private bool _saveChecked = false;
+ /// Gets or sets if the save checkbox status.
+ public bool SaveChecked {
+ get {
+ return _saveChecked;
+ }
+ set {
+ _saveChecked = value;
+ }
+ }
+
+ private bool _saveDisplayed = true;
+ /// Gets or sets if the save checkbox is displayed.
+ /// This value only has effect if Persist is true.
+ public bool SaveDisplayed {
+ get {
+ return _saveDisplayed;
+ }
+ set {
+ _saveDisplayed = value;
+ }
+ }
+
+ private string _target = String.Empty;
+ /// Gets or sets the name of the target for the credentials, typically a server name.
+ public string Target {
+ get {
+ return _target;
+ }
+ set {
+ if (value == null) {
+ throw new ArgumentException("The target cannot be a null value.", "Target");
+ } else if (value.Length > CREDUI.MAX_GENERIC_TARGET_LENGTH) {
+ string message = String.Format(
+ Thread.CurrentThread.CurrentUICulture,
+ "The target has a maximum length of {0} characters.",
+ CREDUI.MAX_GENERIC_TARGET_LENGTH);
+ throw new ArgumentException(message, "Target");
+ }
+ _target = value;
+ }
+ }
+
+ private string _caption = String.Empty;
+ /// Gets or sets the caption of the dialog.
+ /// A null value will cause a system default caption to be used.
+ public string Caption {
+ get {
+ return _caption;
+ }
+ set {
+ if (value != null) {
+ if (value.Length > CREDUI.MAX_CAPTION_LENGTH) {
+ string message = String.Format(
+ Thread.CurrentThread.CurrentUICulture,
+ "The caption has a maximum length of {0} characters.",
+ CREDUI.MAX_CAPTION_LENGTH);
+ throw new ArgumentException(message, "Caption");
+ }
+ }
+ _caption = value;
+ }
+ }
+
+ private string _message = String.Empty;
+ /// Gets or sets the message of the dialog.
+ /// A null value will cause a system default message to be used.
+ public string Message {
+ get {
+ return _message;
+ }
+ set {
+ if (value != null) {
+ if (value.Length > CREDUI.MAX_MESSAGE_LENGTH) {
+ string message = String.Format(
+ Thread.CurrentThread.CurrentUICulture,
+ "The message has a maximum length of {0} characters.",
+ CREDUI.MAX_MESSAGE_LENGTH);
+ throw new ArgumentException(message, "Message");
+ }
+ }
+ _message = value;
+ }
+ }
+
+ private Image _banner = null;
+ /// Gets or sets the image to display on the dialog.
+ /// A null value will cause a system default image to be used.
+ public Image Banner {
+ get {
+ return _banner;
+ }
+ set {
+ if (value != null) {
+ if (value.Width != ValidBannerWidth) {
+ throw new ArgumentException("The banner image width must be 320 pixels.", "Banner");
+ }
+ if (value.Height != ValidBannerHeight) {
+ throw new ArgumentException("The banner image height must be 60 pixels.", "Banner");
+ }
+ }
+ _banner = value;
+ }
+ }
+
+ /// Shows the credentials dialog.
+ /// Returns a DialogResult indicating the user action.
+ public DialogResult Show() {
+ return Show(null, this.Name, this.Password, this.SaveChecked);
+ }
+
+ /// Shows the credentials dialog with the specified save checkbox status.
+ /// True if the save checkbox is checked.
+ /// Returns a DialogResult indicating the user action.
+ public DialogResult Show(bool saveChecked) {
+ return Show(null, this.Name, this.Password, saveChecked);
+ }
+
+ /// Shows the credentials dialog with the specified name.
+ /// The name for the credentials.
+ /// Returns a DialogResult indicating the user action.
+ public DialogResult Show(string name) {
+ return Show(null, name, this.Password, this.SaveChecked);
+ }
+
+ /// Shows the credentials dialog with the specified name and password.
+ /// The name for the credentials.
+ /// The password for the credentials.
+ /// Returns a DialogResult indicating the user action.
+ public DialogResult Show(string name, string password) {
+ return Show(null, name, password, this.SaveChecked);
+ }
+
+ /// Shows the credentials dialog with the specified name, password and save checkbox status.
+ /// The name for the credentials.
+ /// The password for the credentials.
+ /// True if the save checkbox is checked.
+ /// Returns a DialogResult indicating the user action.
+ public DialogResult Show(string name, string password, bool saveChecked) {
+ return Show(null, name, password, saveChecked);
+ }
+
+ /// Shows the credentials dialog with the specified owner.
+ /// The System.Windows.Forms.IWin32Window the dialog will display in front of.
+ /// Returns a DialogResult indicating the user action.
+ public DialogResult Show(IWin32Window owner) {
+ return Show(owner, this.Name, this.Password, this.SaveChecked);
+ }
+
+ /// Shows the credentials dialog with the specified owner and save checkbox status.
+ /// The System.Windows.Forms.IWin32Window the dialog will display in front of.
+ /// True if the save checkbox is checked.
+ /// Returns a DialogResult indicating the user action.
+ public DialogResult Show(IWin32Window owner, bool saveChecked) {
+ return Show(owner, this.Name, this.Password, saveChecked);
+ }
+
+ /// Shows the credentials dialog with the specified owner, name and password.
+ /// The System.Windows.Forms.IWin32Window the dialog will display in front of.
+ /// The name for the credentials.
+ /// The password for the credentials.
+ /// Returns a DialogResult indicating the user action.
+ public DialogResult Show(IWin32Window owner, string name, string password) {
+ return Show(owner, name, password, this.SaveChecked);
+ }
+
+ /// Shows the credentials dialog with the specified owner, name, password and save checkbox status.
+ /// The System.Windows.Forms.IWin32Window the dialog will display in front of.
+ /// The name for the credentials.
+ /// The password for the credentials.
+ /// True if the save checkbox is checked.
+ /// Returns a DialogResult indicating the user action.
+ public DialogResult Show(IWin32Window owner, string name, string password, bool saveChecked) {
+ if ((Environment.OSVersion.Version.Major < 5) || ((Environment.OSVersion.Version.Major == 5) && (Environment.OSVersion.Version.Minor < 1))) {
+ throw new ApplicationException("The Credential Management API requires Windows XP / Windows Server 2003 or later.");
+ }
+ this.Name = name;
+ this.Password = password;
+ this.SaveChecked = saveChecked;
+
+ return ShowDialog(owner);
+ }
+
+ /// Confirmation action to be applied.
+ /// True if the credentials should be persisted.
+ public void Confirm(bool value) {
+ switch (CREDUI.ConfirmCredentials(this.Target, value)) {
+ case CREDUI.ReturnCodes.NO_ERROR:
+ break;
+
+ case CREDUI.ReturnCodes.ERROR_INVALID_PARAMETER:
+ // for some reason, this is encountered when credentials are overwritten
+ break;
+
+ default:
+ throw new ApplicationException("Credential confirmation failed.");
+ }
+ }
+
+ /// Returns a DialogResult indicating the user action.
+ /// The System.Windows.Forms.IWin32Window the dialog will display in front of.
+ ///
+ /// Sets the name, password and SaveChecked accessors to the state of the dialog as it was dismissed by the user.
+ ///
+ private DialogResult ShowDialog(IWin32Window owner) {
+ // set the api call parameters
+ StringBuilder name = new StringBuilder(CREDUI.MAX_USERNAME_LENGTH);
+ name.Append(this.Name);
+
+ StringBuilder password = new StringBuilder(CREDUI.MAX_PASSWORD_LENGTH);
+ password.Append(this.Password);
+
+ int saveChecked = Convert.ToInt32(this.SaveChecked);
+
+ CREDUI.INFO info = GetInfo(owner);
+ CREDUI.FLAGS flags = GetFlags();
+
+ // make the api call
+ CREDUI.ReturnCodes code = CREDUI.PromptForCredentials(
+ ref info,
+ this.Target,
+ IntPtr.Zero, 0,
+ name, CREDUI.MAX_USERNAME_LENGTH,
+ password, CREDUI.MAX_PASSWORD_LENGTH,
+ ref saveChecked,
+ flags
+ );
+
+ // clean up resources
+ if (this.Banner != null) GDI32.DeleteObject(info.hbmBanner);
+
+ // set the accessors from the api call parameters
+ this.Name = name.ToString();
+ this.Password = password.ToString();
+ this.SaveChecked = Convert.ToBoolean(saveChecked);
+
+ return GetDialogResult(code);
+ }
+
+ /// Returns the info structure for dialog display settings.
+ /// The System.Windows.Forms.IWin32Window the dialog will display in front of.
+ private CREDUI.INFO GetInfo(IWin32Window owner) {
+ CREDUI.INFO info = new CREDUI.INFO();
+ if (owner != null) info.hwndParent = owner.Handle;
+ info.pszCaptionText = this.Caption;
+ info.pszMessageText = this.Message;
+ if (this.Banner != null) {
+ info.hbmBanner = new Bitmap(this.Banner, ValidBannerWidth, ValidBannerHeight).GetHbitmap();
+ }
+ info.cbSize = Marshal.SizeOf(info);
+ return info;
+ }
+
+ /// Returns the flags for dialog display options.
+ private CREDUI.FLAGS GetFlags() {
+ CREDUI.FLAGS flags = CREDUI.FLAGS.GENERIC_CREDENTIALS;
+
+ if (this.AlwaysDisplay) {
+ flags = flags | CREDUI.FLAGS.ALWAYS_SHOW_UI;
+ }
+
+ if (this.ExcludeCertificates) {
+ flags = flags | CREDUI.FLAGS.EXCLUDE_CERTIFICATES;
+ }
+
+ if (this.Persist) {
+ flags = flags | CREDUI.FLAGS.EXPECT_CONFIRMATION;
+ if (this.SaveDisplayed) {
+ flags = flags | CREDUI.FLAGS.SHOW_SAVE_CHECK_BOX;
+ } else {
+ flags = flags | CREDUI.FLAGS.PERSIST;
+ }
+ } else {
+ flags = flags | CREDUI.FLAGS.DO_NOT_PERSIST;
+ }
+
+ if (this.KeepName) {
+ flags = flags | CREDUI.FLAGS.KEEP_USERNAME;
+ }
+
+ return flags;
+ }
+
+ /// Returns a DialogResult from the specified code.
+ /// The credential return code.
+ private DialogResult GetDialogResult(CREDUI.ReturnCodes code) {
+ DialogResult result;
+ switch (code) {
+ case CREDUI.ReturnCodes.NO_ERROR:
+ result = DialogResult.OK;
+ break;
+ case CREDUI.ReturnCodes.ERROR_CANCELLED:
+ result = DialogResult.Cancel;
+ break;
+ case CREDUI.ReturnCodes.ERROR_NO_SUCH_LOGON_SESSION:
+ throw new ApplicationException("No such logon session.");
+ case CREDUI.ReturnCodes.ERROR_NOT_FOUND:
+ throw new ApplicationException("Not found.");
+ case CREDUI.ReturnCodes.ERROR_INVALID_ACCOUNT_NAME:
+ throw new ApplicationException("Invalid account name.");
+ case CREDUI.ReturnCodes.ERROR_INSUFFICIENT_BUFFER:
+ throw new ApplicationException("Insufficient buffer.");
+ case CREDUI.ReturnCodes.ERROR_INVALID_PARAMETER:
+ throw new ApplicationException("Invalid parameter.");
+ case CREDUI.ReturnCodes.ERROR_INVALID_FLAGS:
+ throw new ApplicationException("Invalid flags.");
+ default:
+ throw new ApplicationException("Unknown credential result encountered.");
+ }
+ return result;
+ }
+ }
+
+ public sealed class GDI32 {
+ private GDI32() {
+ }
+
+ [DllImport("gdi32.dll", EntryPoint="DeleteObject")]
+ public static extern bool DeleteObject(IntPtr hObject);
+ }
+
+ public sealed class CREDUI {
+ private CREDUI() {
+ }
+
+ /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/authentication_constants.asp
+ public const int MAX_MESSAGE_LENGTH = 100;
+ public const int MAX_CAPTION_LENGTH = 100;
+ public const int MAX_GENERIC_TARGET_LENGTH = 100;
+ public const int MAX_DOMAIN_TARGET_LENGTH = 100;
+ public const int MAX_USERNAME_LENGTH = 100;
+ public const int MAX_PASSWORD_LENGTH = 100;
+
+ ///
+ /// http://www.pinvoke.net/default.aspx/Enums.CREDUI_FLAGS
+ /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/dpapiusercredentials.asp
+ /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/creduipromptforcredentials.asp
+ ///
+ [Flags] public enum FLAGS {
+ INCORRECT_PASSWORD = 0x1,
+ DO_NOT_PERSIST = 0x2,
+ REQUEST_ADMINISTRATOR = 0x4,
+ EXCLUDE_CERTIFICATES = 0x8,
+ REQUIRE_CERTIFICATE = 0x10,
+ SHOW_SAVE_CHECK_BOX = 0x40,
+ ALWAYS_SHOW_UI = 0x80,
+ REQUIRE_SMARTCARD = 0x100,
+ PASSWORD_ONLY_OK = 0x200,
+ VALIDATE_USERNAME = 0x400,
+ COMPLETE_USERNAME = 0x800,
+ PERSIST = 0x1000,
+ SERVER_CREDENTIAL = 0x4000,
+ EXPECT_CONFIRMATION = 0x20000,
+ GENERIC_CREDENTIALS = 0x40000,
+ USERNAME_TARGET_CREDENTIALS = 0x80000,
+ KEEP_USERNAME = 0x100000,
+ }
+
+ /// http://www.pinvoke.net/default.aspx/Enums.CredUIReturnCodes
+ public enum ReturnCodes {
+ NO_ERROR = 0,
+ ERROR_INVALID_PARAMETER = 87,
+ ERROR_INSUFFICIENT_BUFFER = 122,
+ ERROR_INVALID_FLAGS = 1004,
+ ERROR_NOT_FOUND = 1168,
+ ERROR_CANCELLED = 1223,
+ ERROR_NO_SUCH_LOGON_SESSION = 1312,
+ ERROR_INVALID_ACCOUNT_NAME = 1315
+ }
+
+ ///
+ /// http://www.pinvoke.net/default.aspx/Structures.CREDUI_INFO
+ /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/credui_info.asp
+ ///
+ public struct INFO {
+ public int cbSize;
+ public IntPtr hwndParent;
+ [MarshalAs(UnmanagedType.LPWStr)] public string pszMessageText;
+ [MarshalAs(UnmanagedType.LPWStr)] public string pszCaptionText;
+ public IntPtr hbmBanner;
+ }
+
+ ///
+ /// http://www.pinvoke.net/default.aspx/credui.CredUIPromptForCredentialsW
+ /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/creduipromptforcredentials.asp
+ ///
+ [DllImport("credui", EntryPoint="CredUIPromptForCredentialsW", CharSet=CharSet.Unicode)]
+ public static extern ReturnCodes PromptForCredentials(
+ ref INFO creditUR,
+ string targetName,
+ IntPtr reserved1,
+ int iError,
+ StringBuilder userName,
+ int maxUserName,
+ StringBuilder password,
+ int maxPassword,
+ ref int iSave,
+ FLAGS flags
+ );
+
+ ///
+ /// http://www.pinvoke.net/default.aspx/credui.CredUIConfirmCredentials
+ /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/creduiconfirmcredentials.asp
+ ///
+ [DllImport("credui.dll", EntryPoint="CredUIConfirmCredentialsW", CharSet=CharSet.Unicode)]
+ public static extern ReturnCodes ConfirmCredentials(string targetName, bool confirm);
+ }
+}
\ No newline at end of file