Document bitmap transparency and public API
Explain image behavior for each credential tile version, package the README and XML documentation, and complete the public API comments.
This commit is contained in:
@@ -113,7 +113,7 @@ public override CredentialTile2 CreateUserTile(CredentialProviderUser user)
|
||||
}
|
||||
```
|
||||
|
||||
* Create your tile class. Inherit from `CredentialTile2` if you want to create personalized tiles supported by Windows 8 and later, or `CredentialTile1` if you only want to implement a generic tile. Grab the instances of your controls in the `Initialize` method, so you can attach to their properties to read and respond to value changes. Finally, override the `GetCredentials` method, which is called when the user clicks the submit button.
|
||||
* Create your tile class. Inherit from `CredentialTile2` if you want to create personalized tiles supported by Windows 8 and later, or `CredentialTile` if you only want to implement a generic tile. Use `CredentialTile3` when an image must preserve transparency. Grab the instances of your controls in the `Initialize` method, so you can attach to their properties to read and respond to value changes. Finally, override the `GetCredentials` method, which is called when the user clicks the submit button.
|
||||
|
||||
```cs
|
||||
public class MyTile : CredentialTile2
|
||||
@@ -188,10 +188,44 @@ public class MyTile : CredentialTile2
|
||||
};
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* Build your project and you have a functional credential provider!
|
||||
|
||||
## Bitmap transparency
|
||||
|
||||
`CredentialProviderLogoControl` and `UserTileControl` both accept a `Bitmap`. The tile base class controls how Windows receives images that contain transparent or partially transparent pixels.
|
||||
|
||||
| Tile base class | Image behaviour |
|
||||
|-----------------|-----------------|
|
||||
| `CredentialTile` | Renders transparency against the control's `BackgroundColor`. |
|
||||
| `CredentialTile2` | Renders transparency against the control's `BackgroundColor`. |
|
||||
| `CredentialTile3` | Preserves the image's alpha channel and ignores `BackgroundColor`. |
|
||||
|
||||
Existing providers that inherit from `CredentialTile` or `CredentialTile2` keep their current behaviour. The default `BackgroundColor` is `#464646`.
|
||||
|
||||
To preserve transparency, inherit your tile class from `CredentialTile3` and provide a `Bitmap` with an alpha channel. The library selects the image representation required by Windows, so your provider does not need to handle that conversion.
|
||||
|
||||
```cs
|
||||
public class MyTile : CredentialTile3
|
||||
{
|
||||
public MyTile(CredentialProviderBase credentialProvider) : base(credentialProvider)
|
||||
{
|
||||
}
|
||||
|
||||
public MyTile(CredentialProviderBase credentialProvider, CredentialProviderUser user) : base(credentialProvider, user)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<ControlBase> GetControls(UsageScenario cpus)
|
||||
{
|
||||
Bitmap image = LoadTransparentBitmap();
|
||||
yield return new UserTileControl("UserTile", "User tile image", image);
|
||||
yield return new CredentialProviderLogoControl("ProviderLogo", "Credential provider logo", image);
|
||||
}
|
||||
```
|
||||
|
||||
## Installing the credential provider
|
||||
You can use the traditional methods of registering a credential provider (regasm, regsvr32, create registry keys etc), but we've provided a PowerShell module to automatically register your credential provider with a single command.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
namespace Lithnet.CredentialProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// The <c ref="ChangePasswordResponse"/> object is used to communicate the results of a password change operation to LogonUI
|
||||
/// The <see cref="ChangePasswordResponse"/> object communicates the result of a password change operation to LogonUI.
|
||||
/// </summary>
|
||||
public class ChangePasswordResponse
|
||||
{
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Lithnet.CredentialProvider
|
||||
/// ConsentUIData is an abstract base class that represents all the different types of data structures that can be passed to the ConsentUI process for a UAC elevation prompt.
|
||||
/// The static members of the class can be used to retrieve the data structure passed to the ConsentUI process, or to determine if the current process is the ConsentUI process.
|
||||
/// The caller will be provided with one of the concrete implementations of this class, depending on the type of data structure that was passed to the ConsentUI process.
|
||||
/// Use the <see cref="ConsentUIData.ConsentUIType"/> property to determine the type of data structure and cast it to one of the concrete implementations.
|
||||
/// Use the <see cref="Type"/> property to determine the type of data structure and cast it to one of the concrete implementations.
|
||||
/// </summary>
|
||||
public abstract class ConsentUIData
|
||||
{
|
||||
@@ -55,7 +55,7 @@ namespace Lithnet.CredentialProvider
|
||||
/// <summary>
|
||||
/// A series of flags that AppInfo passes to ConsentUI to signify actions that need to
|
||||
/// take place on the UI side.
|
||||
/// This includes specifics around the UI that should be presented & signature verification settings.
|
||||
/// This includes details about the UI that should be presented and the signature verification settings.
|
||||
/// </summary>
|
||||
public ConsentUIFlags Flags => this.header.Flags;
|
||||
|
||||
|
||||
@@ -8,13 +8,20 @@ using Lithnet.CredentialProvider.Interop;
|
||||
namespace Lithnet.CredentialProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// The base class of image-based controls
|
||||
/// Provides common image behaviour for credential provider logo and user tile controls.
|
||||
/// </summary>
|
||||
public abstract class BitmapControl : ControlBase
|
||||
{
|
||||
private Bitmap bitmap;
|
||||
private Color backgroundColor;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an image control.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key for the control.</param>
|
||||
/// <param name="label">The label associated with the control.</param>
|
||||
/// <param name="isProviderLogo"><see langword="true"/> to identify the image as the credential provider logo; otherwise, <see langword="false"/>.</param>
|
||||
/// <param name="bitmap">The initial image displayed by the control.</param>
|
||||
protected BitmapControl(string key, string label, bool isProviderLogo, Bitmap bitmap) :
|
||||
base(key, label, FieldType.TileImage, isProviderLogo ? Guid.Parse(CredProviderConstants.CPFG_CREDENTIAL_PROVIDER_LOGO) : Guid.Empty)
|
||||
{
|
||||
@@ -22,6 +29,10 @@ namespace Lithnet.CredentialProvider
|
||||
this.backgroundColor = Color.FromArgb(70, 70, 70);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an image control by copying an existing image control.
|
||||
/// </summary>
|
||||
/// <param name="source">The image control to copy.</param>
|
||||
protected BitmapControl(BitmapControl source) : base(source)
|
||||
{
|
||||
this.bitmap = source.bitmap;
|
||||
@@ -29,9 +40,9 @@ namespace Lithnet.CredentialProvider
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the background color used to replace transparent pixels for <see cref="CredentialTile"/> and <see cref="CredentialTile2"/>. This defaults to #707070.
|
||||
/// Gets or sets the background color used when an image that contains transparency is displayed by a <see cref="CredentialTile"/> or <see cref="CredentialTile2"/>.
|
||||
/// </summary>
|
||||
/// <remarks>This property does not apply to <see cref="CredentialTile3"/>.</remarks>
|
||||
/// <remarks>The default color is #464646. A <see cref="CredentialTile3"/> preserves the image's alpha channel and does not use this property.</remarks>
|
||||
public Color BackgroundColor
|
||||
{
|
||||
get { return this.backgroundColor; }
|
||||
@@ -46,7 +57,7 @@ namespace Lithnet.CredentialProvider
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The image to be displayed
|
||||
/// Gets or sets the image displayed by the control.
|
||||
/// </summary>
|
||||
public Bitmap Bitmap
|
||||
{
|
||||
|
||||
@@ -10,13 +10,13 @@ namespace Lithnet.CredentialProvider
|
||||
private bool isChecked;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <c ref="CheckboxControl"/> control
|
||||
/// Creates a new <see cref="CheckboxControl"/> control.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key for this control</param>
|
||||
public CheckboxControl(string key) : this(key, null) { }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <c ref="CheckboxControl"/> control
|
||||
/// Creates a new <see cref="CheckboxControl"/> control.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key for this control</param>
|
||||
/// <param name="label">The label associated with the control</param>
|
||||
|
||||
@@ -10,13 +10,13 @@ namespace Lithnet.CredentialProvider
|
||||
private int selectedItemIndex;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <c ref="ComboboxControl"/> control
|
||||
/// Creates a new <see cref="ComboboxControl"/> control.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key for this control</param>
|
||||
public ComboboxControl(string key) : this(key, null) { }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <c ref="ComboboxControl"/> control
|
||||
/// Creates a new <see cref="ComboboxControl"/> control.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key for this control</param>
|
||||
/// <param name="label">The label associated with the control</param>
|
||||
|
||||
@@ -9,13 +9,13 @@ namespace Lithnet.CredentialProvider
|
||||
public class CommandLinkControl : ControlBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new <c ref="CommandLinkControl"/> control
|
||||
/// Creates a new <see cref="CommandLinkControl"/> control.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key for this control</param>
|
||||
public CommandLinkControl(string key) : this(key, null) { }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <c ref="CommandLinkControl"/> control
|
||||
/// Creates a new <see cref="CommandLinkControl"/> control.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key for this control</param>
|
||||
/// <param name="label">The label associated with the control</param>
|
||||
|
||||
@@ -18,6 +18,10 @@ namespace Lithnet.CredentialProvider
|
||||
private string label;
|
||||
private FieldOptions options;
|
||||
private protected ICredentialProviderLogger logger;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when the value of a public property changes.
|
||||
/// </summary>
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
private protected ControlBase(ControlBase source)
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
namespace Lithnet.CredentialProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a control that provides the credential UI with the name of this credential provider
|
||||
/// Represents a control that provides the credential UI with the name of this credential provider.
|
||||
/// </summary>
|
||||
public class CredentialProviderLabelControl : SmallLabelControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new <c ref="CredentialProviderLabelControl"/> control
|
||||
/// Creates a new <see cref="CredentialProviderLabelControl"/> control.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key for this control</param>
|
||||
/// <param name="label">The label associated with the control</param>
|
||||
/// <param name="key">The unique key for this control.</param>
|
||||
public CredentialProviderLabelControl(string key) : this(key, null) { }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <c ref="CredentialProviderLabelControl"/> control
|
||||
/// Creates a new <see cref="CredentialProviderLabelControl"/> control.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key for this control</param>
|
||||
/// <param name="label">The label associated with the control</param>
|
||||
/// <param name="key">The unique key for this control.</param>
|
||||
/// <param name="label">The label associated with the control.</param>
|
||||
public CredentialProviderLabelControl(string key, string label) : base(key, label, true)
|
||||
{
|
||||
this.State = FieldState.DisplayInDeselectedTile;
|
||||
|
||||
@@ -3,29 +3,30 @@
|
||||
namespace Lithnet.CredentialProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a control that provides the credential UI with the logo of this credential provider
|
||||
/// Represents a control that provides the credential UI with the logo of this credential provider.
|
||||
/// </summary>
|
||||
/// <remarks>See <see cref="BitmapControl.BackgroundColor"/> for the image transparency behaviour of each credential tile version.</remarks>
|
||||
public class CredentialProviderLogoControl : BitmapControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new <c ref="CredentialProviderLogoControl"/> control
|
||||
/// Creates a new <see cref="CredentialProviderLogoControl"/> control.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key for this control</param>
|
||||
/// <param name="key">The unique key for this control.</param>
|
||||
public CredentialProviderLogoControl(string key) : this(key, null, null) { }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <c ref="CredentialProviderLogoControl"/> control
|
||||
/// Creates a new <see cref="CredentialProviderLogoControl"/> control.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key for this control</param>
|
||||
/// <param name="label">The label associated with the control. This value is not displayed to the user</param>
|
||||
/// <param name="key">The unique key for this control.</param>
|
||||
/// <param name="label">The label associated with the control. This value is not displayed to the user.</param>
|
||||
public CredentialProviderLogoControl(string key, string label) : this(key, label, null) { }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <c ref="CredentialProviderLogoControl"/> control
|
||||
/// Creates a new <see cref="CredentialProviderLogoControl"/> control.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key for this control</param>
|
||||
/// <param name="label">The label associated with the control</param>
|
||||
/// <param name="bitmap">The bitmap to use as the logo</param>
|
||||
/// <param name="key">The unique key for this control.</param>
|
||||
/// <param name="label">The label associated with the control.</param>
|
||||
/// <param name="bitmap">The bitmap to use as the logo.</param>
|
||||
public CredentialProviderLogoControl(string key, string label, Bitmap bitmap) : base(key, label, true, bitmap)
|
||||
{
|
||||
this.State = FieldState.DisplayInDeselectedTile;
|
||||
|
||||
@@ -12,13 +12,13 @@ namespace Lithnet.CredentialProvider
|
||||
private string password;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <c ref="InsecurePasswordTextboxControl"/> control
|
||||
/// Creates a new <see cref="InsecurePasswordTextboxControl"/> control.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key for this control</param>
|
||||
public InsecurePasswordTextboxControl(string key) : this(key, null) { }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <c ref="InsecurePasswordTextboxControl"/> control
|
||||
/// Creates a new <see cref="InsecurePasswordTextboxControl"/> control.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key for this control</param>
|
||||
/// <param name="label">The label associated with the control</param>
|
||||
|
||||
@@ -8,13 +8,13 @@ namespace Lithnet.CredentialProvider
|
||||
public class LargeLabelControl : ControlBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new <c ref="LargeLabelControl"/> control
|
||||
/// Creates a new <see cref="LargeLabelControl"/> control.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key for this control</param>
|
||||
public LargeLabelControl(string key) : this(key, null) { }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <c ref="LargeLabelControl"/> control
|
||||
/// Creates a new <see cref="LargeLabelControl"/> control.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key for this control</param>
|
||||
/// <param name="label">The label associated with the control</param>
|
||||
|
||||
@@ -13,13 +13,13 @@ namespace Lithnet.CredentialProvider
|
||||
private SecureString password;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <c ref="SecurePasswordTextboxControl"/> control
|
||||
/// Creates a new <see cref="SecurePasswordTextboxControl"/> control.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key for this control</param>
|
||||
public SecurePasswordTextboxControl(string key) : this(key, null) { }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <c ref="SecurePasswordTextboxControl"/> control
|
||||
/// Creates a new <see cref="SecurePasswordTextboxControl"/> control.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key for this control</param>
|
||||
/// <param name="label">The label associated with the control</param>
|
||||
|
||||
@@ -11,7 +11,14 @@ namespace Lithnet.CredentialProvider
|
||||
{
|
||||
private readonly List<string> backingList = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// Occurs after an item is added to the list.
|
||||
/// </summary>
|
||||
public event EventHandler<string> ItemAdded;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs after an item is removed from the list. The event value is the former zero-based index of the item.
|
||||
/// </summary>
|
||||
public event EventHandler<int> ItemRemoved;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -9,13 +9,13 @@ namespace Lithnet.CredentialProvider
|
||||
public class SmallLabelControl : ControlBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new <c ref="SmallLabelControl"/> control
|
||||
/// Creates a new <see cref="SmallLabelControl"/> control.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key for this control</param>
|
||||
public SmallLabelControl(string key) : this(key, null, false) { }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <c ref="SmallLabelControl"/> control
|
||||
/// Creates a new <see cref="SmallLabelControl"/> control.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key for this control</param>
|
||||
/// <param name="label">The label associated with the control</param>
|
||||
|
||||
@@ -10,14 +10,14 @@ namespace Lithnet.CredentialProvider
|
||||
private ControlBase adjacentToControl;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <c ref="SubmitButtonControl"/> control
|
||||
/// Creates a new <see cref="SubmitButtonControl"/> control.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key for this control</param>
|
||||
/// <param name="adjacentToControl">The control that the submit button should appear adjacent to</param>
|
||||
public SubmitButtonControl(string key, ControlBase adjacentToControl) : this(key, null, adjacentToControl) { }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <c ref="SubmitButtonControl"/> control
|
||||
/// Creates a new <see cref="SubmitButtonControl"/> control.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key for this control</param>
|
||||
/// <param name="label">The label associated with the control</param>
|
||||
|
||||
@@ -13,13 +13,13 @@ namespace Lithnet.CredentialProvider
|
||||
private TextboxControl(TextboxControl source) : base(source) { }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <c ref="TextboxControl"/> control
|
||||
/// Creates a new <see cref="TextboxControl"/> control.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key for this control</param>
|
||||
public TextboxControl(string key) : this(key, null) { }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <c ref="TextboxControl"/> control
|
||||
/// Creates a new <see cref="TextboxControl"/> control.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key for this control</param>
|
||||
/// <param name="label">The label associated with the control</param>
|
||||
|
||||
@@ -3,29 +3,30 @@
|
||||
namespace Lithnet.CredentialProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// A control that displays the user's tile image
|
||||
/// Represents a control that displays the user's tile image.
|
||||
/// </summary>
|
||||
/// <remarks>See <see cref="BitmapControl.BackgroundColor"/> for the image transparency behaviour of each credential tile version.</remarks>
|
||||
public class UserTileControl : BitmapControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new <c ref="UserTileControl"/> control
|
||||
/// Creates a new <see cref="UserTileControl"/> control.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key for this control</param>
|
||||
/// <param name="key">The unique key for this control.</param>
|
||||
public UserTileControl(string key) : this(key, null, null) { }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <c ref="UserTileControl"/> control
|
||||
/// Creates a new <see cref="UserTileControl"/> control.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key for this control</param>
|
||||
/// <param name="label">The label associated with the control</param>
|
||||
/// <param name="key">The unique key for this control.</param>
|
||||
/// <param name="label">The label associated with the control.</param>
|
||||
public UserTileControl(string key, string label) : this(key, label, null) { }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <c ref="UserTileControl"/> control
|
||||
/// Creates a new <see cref="UserTileControl"/> control.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key for this control</param>
|
||||
/// <param name="label">The label associated with the control</param>
|
||||
/// <param name="bitmap">The bitmap to use as the user's tile image</param>
|
||||
/// <param name="key">The unique key for this control.</param>
|
||||
/// <param name="label">The label associated with the control.</param>
|
||||
/// <param name="bitmap">The bitmap to use as the user's tile image.</param>
|
||||
public UserTileControl(string key, string label, Bitmap bitmap) : base(key, label, false, bitmap) { }
|
||||
|
||||
private UserTileControl(UserTileControl source) : base(source) { }
|
||||
|
||||
@@ -67,6 +67,10 @@ namespace Lithnet.CredentialProvider
|
||||
/// </summary>
|
||||
public CredentialSerialization InboundSerialization { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a credential provider and obtains its identifier from the <see cref="GuidAttribute"/> on the derived class.
|
||||
/// </summary>
|
||||
/// <exception cref="InvalidOperationException">The derived credential provider class does not have a <see cref="GuidAttribute"/>.</exception>
|
||||
protected CredentialProviderBase()
|
||||
{
|
||||
this.LoggerFactory = this.GetLoggerFactory();
|
||||
@@ -84,13 +88,13 @@ namespace Lithnet.CredentialProvider
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a logger factory. Override this method and provide an implementation of <c ref="ILoggerFactory"/> to enable credential provider logging
|
||||
/// Gets a logger factory. Override this method and provide an implementation of <see cref="ICredentialProviderLoggerFactory"/> to enable credential provider logging.
|
||||
/// </summary>
|
||||
/// <returns>An ILoggerFactory instance</returns>
|
||||
/// <returns>An <see cref="ICredentialProviderLoggerFactory"/> instance.</returns>
|
||||
protected virtual ICredentialProviderLoggerFactory GetLoggerFactory() { return TraceLoggerFactory.Instance; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating if the credential provider supports the <c ref="UsageScenario"/> provided by LogonUI or CredUI
|
||||
/// Gets a value indicating whether the credential provider supports the <see cref="UsageScenario"/> provided by LogonUI or CredUI.
|
||||
/// </summary>
|
||||
/// <param name="cpus">The usage scenario</param>
|
||||
/// <param name="dwFlags">Additional flags provided by CredUI</param>
|
||||
@@ -116,10 +120,22 @@ namespace Lithnet.CredentialProvider
|
||||
/// </summary>
|
||||
public abstract bool ShouldIncludeGenericTile();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the tile that the credential provider reports as the default credential.
|
||||
/// </summary>
|
||||
protected internal CredentialTile DefaultTile { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value that indicates whether Logon UI or Credential UI should immediately request serialization from the default tile.
|
||||
/// </summary>
|
||||
protected internal bool DefaultTileAutoLogon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the default tile, configures its automatic logon request, and notifies the credential UI to enumerate the tiles again.
|
||||
/// </summary>
|
||||
/// <param name="tile">A tile in the current <see cref="Tiles"/> collection.</param>
|
||||
/// <param name="autoLogon"><see langword="true"/> to make Logon UI or Credential UI immediately request serialization from the default tile; otherwise, <see langword="false"/>.</param>
|
||||
/// <exception cref="InvalidOperationException"><paramref name="tile"/> is not in the current <see cref="Tiles"/> collection.</exception>
|
||||
public void SetDefaultTile(CredentialTile tile, bool autoLogon)
|
||||
{
|
||||
if (this.DefaultTile == tile && this.DefaultTileAutoLogon == autoLogon)
|
||||
@@ -188,7 +204,7 @@ namespace Lithnet.CredentialProvider
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method is used to generate the generic tile for this credential provider. This is called when <c ref="ShouldIncludeGenericTile"/> return true
|
||||
/// Creates the generic tile for this credential provider. This method is called when <see cref="ShouldIncludeGenericTile"/> returns <see langword="true"/>.
|
||||
/// </summary>
|
||||
public abstract CredentialTile CreateGenericTile();
|
||||
|
||||
|
||||
@@ -15,6 +15,10 @@ namespace Lithnet.CredentialProvider
|
||||
private protected ICredentialProviderCredentialEvents2 events2;
|
||||
private protected ControlCollection controls;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a version 1 credential tile.
|
||||
/// </summary>
|
||||
/// <param name="credentialProvider">The credential provider that owns this tile.</param>
|
||||
protected CredentialTile(CredentialProviderBase credentialProvider)
|
||||
{
|
||||
this.CredentialProvider = credentialProvider;
|
||||
@@ -34,7 +38,7 @@ namespace Lithnet.CredentialProvider
|
||||
public bool IsSelected { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value that indicates if the user should be automatically logged on when the tile is selected. The tile must also have IsDefault set to true.
|
||||
/// Gets a value that indicates whether Logon UI or Credential UI should immediately request serialization from this tile. The tile must also be the default tile.
|
||||
/// </summary>
|
||||
public bool IsDefaultTileAutoLogon
|
||||
{
|
||||
@@ -111,7 +115,7 @@ namespace Lithnet.CredentialProvider
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates to the host that multiple updates need to be made to the fields, and that it should delay updating the UI until <see cref="EndBulkFieldUpdate" is called/>
|
||||
/// Indicates to the host that multiple fields will be updated and that it should delay updating the UI until <see cref="EndBulkFieldUpdate"/> is called.
|
||||
/// </summary>
|
||||
/// <exception cref="InvalidOperationException"></exception>
|
||||
public void BeginBulkFieldUpdate()
|
||||
@@ -176,7 +180,7 @@ namespace Lithnet.CredentialProvider
|
||||
protected virtual void OnDeselected() { }
|
||||
|
||||
/// <summary>
|
||||
/// Called just before credentials are serialized and returned to the host
|
||||
/// Called immediately before credentials are serialized and returned to the host
|
||||
/// </summary>
|
||||
protected virtual void OnBeforeSerialize() { }
|
||||
|
||||
|
||||
@@ -23,8 +23,17 @@
|
||||
/// <remarks>This does not apply in scenarios where a personalized tile is provided</remarks>
|
||||
public GenericTileDisplayMode GenericTileDisplayMode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a generic version 2 credential tile.
|
||||
/// </summary>
|
||||
/// <param name="credentialProvider">The credential provider that owns this tile.</param>
|
||||
protected CredentialTile2(CredentialProviderBase credentialProvider) : this(credentialProvider, null) { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a version 2 credential tile for a user.
|
||||
/// </summary>
|
||||
/// <param name="credentialProvider">The credential provider that owns this tile.</param>
|
||||
/// <param name="user">The user represented by this tile, or <see langword="null"/> for a generic tile.</param>
|
||||
protected CredentialTile2(CredentialProviderBase credentialProvider, CredentialProviderUser user) : base(credentialProvider)
|
||||
{
|
||||
this.User = user;
|
||||
|
||||
@@ -4,13 +4,22 @@ using Lithnet.CredentialProvider.Interop;
|
||||
namespace Lithnet.CredentialProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a user credential tile that implements the functionality of <see cref="CredentialTile"/> and <see cref="CredentialTile2"/>, but includes support for dynamically updating bitmap images.
|
||||
/// Represents a version 3 credential tile that preserves transparency in bitmap controls.
|
||||
/// </summary>
|
||||
/// <remarks>This interface is public, but undocumented by Microsoft. It is recommended to use <see cref="CredentialTile2"/> tiles unless this specific functionality is needed</remarks>
|
||||
/// <remarks>Inherit from this class when a <see cref="CredentialProviderLogoControl"/> or <see cref="UserTileControl"/> must preserve the image's alpha channel. The <see cref="BitmapControl.BackgroundColor"/> property does not apply to this tile type. Microsoft does not publish documentation for the underlying version 3 credential interfaces, so use <see cref="CredentialTile2"/> unless you need image transparency.</remarks>
|
||||
public abstract partial class CredentialTile3 : CredentialTile2
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a generic version 3 credential tile.
|
||||
/// </summary>
|
||||
/// <param name="credentialProvider">The credential provider that owns this tile.</param>
|
||||
protected CredentialTile3(CredentialProviderBase credentialProvider) : this(credentialProvider, null) { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a version 3 credential tile for a user.
|
||||
/// </summary>
|
||||
/// <param name="credentialProvider">The credential provider that owns this tile.</param>
|
||||
/// <param name="user">The user represented by this tile, or <see langword="null"/> for a generic tile.</param>
|
||||
protected CredentialTile3(CredentialProviderBase credentialProvider, CredentialProviderUser user) : base(credentialProvider, user) { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
namespace Lithnet.CredentialProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the reason that Consent UI received an elevation request.
|
||||
/// </summary>
|
||||
public enum ConsentUIElevationReason
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -2,9 +2,15 @@
|
||||
|
||||
namespace Lithnet.CredentialProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies how Consent UI should display and verify an elevation request.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum ConsentUIFlags
|
||||
{
|
||||
/// <summary>
|
||||
/// The purpose of the 0x01 flag is not documented.
|
||||
/// </summary>
|
||||
SkipSignatureVerification = 0x01,
|
||||
|
||||
/// <summary>
|
||||
@@ -12,8 +18,19 @@ namespace Lithnet.CredentialProvider
|
||||
/// </summary>
|
||||
SecureDesktop = 0x02,
|
||||
|
||||
/// <summary>
|
||||
/// The purpose of the 0x04 flag is not documented.
|
||||
/// </summary>
|
||||
Unknown1 = 0x04,
|
||||
|
||||
/// <summary>
|
||||
/// The purpose of the 0x08 flag is not documented.
|
||||
/// </summary>
|
||||
Unknown2 = 0x08,
|
||||
|
||||
/// <summary>
|
||||
/// The purpose of the 0x10 flag is not documented.
|
||||
/// </summary>
|
||||
Unknown3 = 0x10,
|
||||
|
||||
/// <summary>
|
||||
@@ -42,6 +59,9 @@ namespace Lithnet.CredentialProvider
|
||||
/// </summary>
|
||||
AutoElevationOther = 0x100,
|
||||
|
||||
/// <summary>
|
||||
/// The purpose of the 0x200 flag is not documented.
|
||||
/// </summary>
|
||||
Unknown4 = 0x200,
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -2,10 +2,24 @@
|
||||
|
||||
namespace Lithnet.CredentialProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the Windows Installer action described by Consent UI data.
|
||||
/// </summary>
|
||||
public enum ConsentUIMsiAction : uint
|
||||
{
|
||||
/// <summary>
|
||||
/// Installs a Windows Installer package.
|
||||
/// </summary>
|
||||
Install = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Uninstalls a Windows Installer package.
|
||||
/// </summary>
|
||||
Uninstall = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Updates or repairs an installed Windows Installer package.
|
||||
/// </summary>
|
||||
Update = 2
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,28 @@
|
||||
namespace Lithnet.CredentialProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies how Consent UI obtains approval for an elevation request.
|
||||
/// </summary>
|
||||
public enum ConsentUIPromptType
|
||||
{
|
||||
/// <summary>
|
||||
/// The prompt type is not known.
|
||||
/// </summary>
|
||||
Unknown = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Uses the Consent UI automatic administrator mode.
|
||||
/// </summary>
|
||||
AutomaticAdmin = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Requests consent from an administrator.
|
||||
/// </summary>
|
||||
Consent = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Requests administrator credentials.
|
||||
/// </summary>
|
||||
Credentials = 3
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,38 @@
|
||||
namespace Lithnet.CredentialProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Identifies the type of data supplied to Consent UI for an elevation request.
|
||||
/// </summary>
|
||||
public enum ConsentUIType
|
||||
{
|
||||
/// <summary>
|
||||
/// The data describes an executable file.
|
||||
/// </summary>
|
||||
Exe = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The data describes an elevated COM object.
|
||||
/// </summary>
|
||||
Com = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The data describes a Windows Installer package.
|
||||
/// </summary>
|
||||
Msi = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The data describes an ActiveX installation.
|
||||
/// </summary>
|
||||
ActiveX = 3,
|
||||
|
||||
/// <summary>
|
||||
/// The data uses the CredCollect structure. The purpose of this structure is not documented.
|
||||
/// </summary>
|
||||
CredCollect = 4,
|
||||
|
||||
/// <summary>
|
||||
/// The data describes a packaged application.
|
||||
/// </summary>
|
||||
Msix = 5
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,9 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Lithnet.CredentialProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies options that control the Windows credential user interface.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum CredUIWinFlags
|
||||
{
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
namespace Lithnet.CredentialProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies how the credential UI should continue after a credential provider handles a serialization request.
|
||||
/// </summary>
|
||||
public enum SerializationResponse
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
/// <summary>
|
||||
/// Workstation unlock. Credential providers that implement this scenario should be prepared to serialize credentials to the local authority for authentication. These credential providers also need to enumerate the currently logged-in user as the default tile.
|
||||
/// </summary>
|
||||
/// <remarks> Starting in Windows 10, the CPUS_LOGON and CPUS_UNLOCK_WORKSTATION user scenarios have been combined. This enables the system to support multiple users logging into a machine without creating and switching sessions unnecessarily. Any user on the machine can log into it once it has been locked without needing to back out of a current session and create a new one. Because of this, CPUS_LOGON can be used both for logging onto a system or when a workstation is unlocked. However, CPUS_LOGON cannot be used in all cases. Because of policy restrictions imposed by various systems, sometimes it is necessary for the user scenario to be CPUS_UNLOCK_WORKSTATION. Your credential provider should be robust enough to create the appropriate credential structure based on the scenario given to it. Windows will request the appropriate user scenario based on the situation. Some of the factors that impact whether or not a CPUS_UNLOCK_WORKSTATION scenario must be used include the following. Note that this is just a subset of possibilities.
|
||||
/// <remarks> Starting in Windows 10, the CPUS_LOGON and CPUS_UNLOCK_WORKSTATION user scenarios have been combined. This enables the system to support multiple users logging into a machine without creating and switching sessions unnecessarily. Any user on the machine can log into it once it has been locked without needing to back out of a current session and create a new one. Because of this, CPUS_LOGON can be used both for logging onto a system or when a workstation is unlocked. However, CPUS_LOGON cannot be used in all cases. Because of policy restrictions imposed by various systems, sometimes it is necessary for the user scenario to be CPUS_UNLOCK_WORKSTATION. Your credential provider should be robust enough to create the appropriate credential structure based on the scenario given to it. Windows will request the appropriate user scenario based on the situation. Some of the factors that impact whether or not a CPUS_UNLOCK_WORKSTATION scenario must be used include the following. This is a subset of the possible factors.
|
||||
/// - The operating system of the device.
|
||||
/// - Whether this is a console or remote session.
|
||||
/// - Group policies such as hiding entry points for fast user switching, or interactive logon that does not display the user's last name.
|
||||
@@ -31,7 +31,7 @@
|
||||
ChangePassword,
|
||||
|
||||
/// <summary>
|
||||
/// Credential UI. This scenario enables you to use credentials serialized by the credential provider to be used as authentication on remote machines. This is also the scenario used for over-the-shoulder prompting in User Access Control. This scenario uses a different instance of the credential provider than the one used for <c ref="Logon"/>, <c ref="UnlockWorkstation"/>, and <c ref="ChangePassword"/>, so the state of the credential provider cannot be maintained across the different scenarios.
|
||||
/// Credential UI. This scenario enables you to use credentials serialized by the credential provider as authentication on remote machines. This is also the scenario used for over-the-shoulder prompting in User Access Control. This scenario uses a different instance of the credential provider than the one used for <see cref="Logon"/>, <see cref="UnlockWorkstation"/>, and <see cref="ChangePassword"/>, so the state of the credential provider cannot be maintained across the different scenarios.
|
||||
/// </summary>
|
||||
CredUI,
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
|
||||
<LangVersion>9</LangVersion>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
@@ -25,6 +26,7 @@
|
||||
<IsPackable>true</IsPackable>
|
||||
<PackageId>Lithnet.CredentialProvider</PackageId>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<RepositoryUrl>https://github.com/lithnet/windows-credential-provider</RepositoryUrl>
|
||||
<SupportUrl>https://github.com/lithnet/windows-credential-provider</SupportUrl>
|
||||
<PackageOutputPath>D:\dev\nuget\packages</PackageOutputPath>
|
||||
@@ -50,6 +52,10 @@
|
||||
</AssemblyAttribute>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="..\..\README.md" Pack="true" PackagePath="\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
|
||||
@@ -2,16 +2,40 @@
|
||||
|
||||
namespace Lithnet.CredentialProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Receives log messages from a credential provider and its credential tiles.
|
||||
/// </summary>
|
||||
public interface ICredentialProviderLogger
|
||||
{
|
||||
/// <summary>
|
||||
/// Logs an error message and its associated exception.
|
||||
/// </summary>
|
||||
/// <param name="ex">The exception associated with the error.</param>
|
||||
/// <param name="message">The error message.</param>
|
||||
void LogError(Exception ex, string message);
|
||||
|
||||
/// <summary>
|
||||
/// Logs an error message.
|
||||
/// </summary>
|
||||
/// <param name="message">The error message.</param>
|
||||
void LogError(string message);
|
||||
|
||||
/// <summary>
|
||||
/// Logs a trace message.
|
||||
/// </summary>
|
||||
/// <param name="message">The trace message.</param>
|
||||
void LogTrace(string message);
|
||||
|
||||
/// <summary>
|
||||
/// Logs an informational message.
|
||||
/// </summary>
|
||||
/// <param name="message">The informational message.</param>
|
||||
void LogInformation(string message);
|
||||
|
||||
/// <summary>
|
||||
/// Logs a warning message.
|
||||
/// </summary>
|
||||
/// <param name="message">The warning message.</param>
|
||||
void LogWarning(string message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,23 @@
|
||||
|
||||
namespace Lithnet.CredentialProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates loggers for credential provider components.
|
||||
/// </summary>
|
||||
public interface ICredentialProviderLoggerFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a logger for the specified component type.
|
||||
/// </summary>
|
||||
/// <param name="type">The type that will write log messages.</param>
|
||||
/// <returns>A logger for the specified type.</returns>
|
||||
ICredentialProviderLogger CreateLogger(Type type);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a logger for the specified component type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type that will write log messages.</typeparam>
|
||||
/// <returns>A logger for the specified type.</returns>
|
||||
ICredentialProviderLogger CreateLogger<T>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,28 +3,52 @@ using System.Diagnostics;
|
||||
|
||||
namespace Lithnet.CredentialProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes credential provider log messages to <see cref="Trace"/>.
|
||||
/// </summary>
|
||||
public class TraceLogger : ICredentialProviderLogger
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes an error message and its associated exception to <see cref="Trace"/>.
|
||||
/// </summary>
|
||||
/// <param name="ex">The exception associated with the error.</param>
|
||||
/// <param name="v">The error message.</param>
|
||||
public void LogError(Exception ex, string v)
|
||||
{
|
||||
Trace.WriteLine($"{v}\r\n\r\n{ex?.ToString()}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an error message to <see cref="Trace"/>.
|
||||
/// </summary>
|
||||
/// <param name="v">The error message.</param>
|
||||
public void LogError(string v)
|
||||
{
|
||||
Trace.WriteLine(v);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an informational message to <see cref="Trace"/>.
|
||||
/// </summary>
|
||||
/// <param name="message">The informational message.</param>
|
||||
public void LogInformation(string message)
|
||||
{
|
||||
Trace.WriteLine(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a trace message to <see cref="Trace"/>.
|
||||
/// </summary>
|
||||
/// <param name="v">The trace message.</param>
|
||||
public void LogTrace(string v)
|
||||
{
|
||||
Trace.WriteLine(v);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a warning message to <see cref="Trace"/>.
|
||||
/// </summary>
|
||||
/// <param name="message">The warning message.</param>
|
||||
public void LogWarning(string message)
|
||||
{
|
||||
Trace.WriteLine(message);
|
||||
|
||||
@@ -2,13 +2,26 @@
|
||||
|
||||
namespace Lithnet.CredentialProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates <see cref="TraceLogger"/> instances.
|
||||
/// </summary>
|
||||
public class TraceLoggerFactory : ICredentialProviderLoggerFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a trace logger for the specified component type.
|
||||
/// </summary>
|
||||
/// <param name="type">The type that will write log messages.</param>
|
||||
/// <returns>A trace logger for the specified type.</returns>
|
||||
public ICredentialProviderLogger CreateLogger(Type type)
|
||||
{
|
||||
return new TraceLogger();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a trace logger for the specified component type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type that will write log messages.</typeparam>
|
||||
/// <returns>A trace logger for the specified type.</returns>
|
||||
public ICredentialProviderLogger CreateLogger<T>()
|
||||
{
|
||||
return new TraceLogger();
|
||||
@@ -16,6 +29,9 @@ namespace Lithnet.CredentialProvider
|
||||
|
||||
private static readonly TraceLoggerFactory loggerFactory = new TraceLoggerFactory();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the shared trace logger factory.
|
||||
/// </summary>
|
||||
public static ICredentialProviderLoggerFactory Instance => loggerFactory;
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -101,6 +101,7 @@ namespace Lithnet.CredentialProvider.Samples
|
||||
|
||||
private static Bitmap CreateTransparentUserTile()
|
||||
{
|
||||
// CredentialTile3 preserves the alpha channel in this image. CredentialTile and CredentialTile2 render it against the control's BackgroundColor.
|
||||
Bitmap image = new Bitmap(128, 128, PixelFormat.Format32bppArgb);
|
||||
|
||||
using (Graphics graphics = Graphics.FromImage(image))
|
||||
|
||||
+3
@@ -5,6 +5,9 @@ using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Lithnet.CredentialProvider.Samples
|
||||
{
|
||||
/// <summary>
|
||||
/// Demonstrates a version 3 credential tile that preserves image transparency.
|
||||
/// </summary>
|
||||
public class TestCredentialProviderTile : CredentialTile3
|
||||
{
|
||||
private TextboxControl UsernameControl;
|
||||
|
||||
Reference in New Issue
Block a user