From 3fe3999e0db4f728d5cd4fe9550a9ad827e34deb Mon Sep 17 00:00:00 2001 From: Ryan Newington Date: Mon, 21 Oct 2024 06:43:05 +1100 Subject: [PATCH] Refactor default and auto-logon tile handling Refactored `CredentialProviderBase` and `CredentialTile` to improve the handling of default and auto-logon tiles. Key changes include: - Introduced `SetDefaultTile` method with validation and tile refresh. - Refactored `IsAutoLogon` and `IsDefault` properties to be read only properties. - Added `ShouldAutoLogon` method to be called when a tile is selected. --- ...dentialProviderBase.ICredentialProvider.cs | 21 +++++++-------- .../CredentialProviderBase.cs | 24 ++++++++++++++++- ...ntialTile.ICredentialProviderCredential.cs | 4 +-- .../CredentialTile.cs | 27 +++++++++---------- 4 files changed, 47 insertions(+), 29 deletions(-) diff --git a/src/Lithnet.CredentialProvider/CredentialProviderBase.ICredentialProvider.cs b/src/Lithnet.CredentialProvider/CredentialProviderBase.ICredentialProvider.cs index a52a5e7..9d0cd1f 100644 --- a/src/Lithnet.CredentialProvider/CredentialProviderBase.ICredentialProvider.cs +++ b/src/Lithnet.CredentialProvider/CredentialProviderBase.ICredentialProvider.cs @@ -169,23 +169,20 @@ namespace Lithnet.CredentialProvider this.notifyOnTileCollectionChange = true; - var autoLogonTile = this.Tiles.FirstOrDefault(t => t.IsAutoLogon); - var defaultTile = this.Tiles.FirstOrDefault(t => t.IsDefault); + var defaultTile = this.DefaultTile; - uint defaultIndex = CREDENTIAL_PROVIDER_NO_DEFAULT; - if (autoLogonTile != null) + if (defaultTile != null) { - defaultIndex = (uint)this.tiles.IndexOf(autoLogonTile); - } - else if (defaultTile != null) - { - defaultIndex = (uint)this.tiles.IndexOf(defaultTile); + var index = this.tiles.IndexOf(defaultTile); + + if (index >= 0) + { + pdwDefault = (uint)index; + pbAutoLogonWithDefault = this.DefaultTileAutoLogon ? 1 : 0; + } } pdwCount = (uint)this.Tiles.Count; - pdwDefault = defaultIndex; - pbAutoLogonWithDefault = autoLogonTile == null ? 0 : 1; - this.logger.LogTrace($"GetCredentialCount returning pdwCount: {pdwCount}, pdwDefault: {pdwDefault}, pbAutoLogonWithDefault: {pbAutoLogonWithDefault}"); return HRESULT.S_OK; diff --git a/src/Lithnet.CredentialProvider/CredentialProviderBase.cs b/src/Lithnet.CredentialProvider/CredentialProviderBase.cs index 7501830..b1fb490 100644 --- a/src/Lithnet.CredentialProvider/CredentialProviderBase.cs +++ b/src/Lithnet.CredentialProvider/CredentialProviderBase.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Reflection; using System.Runtime.InteropServices; using Lithnet.CredentialProvider.Interop; @@ -114,7 +115,28 @@ namespace Lithnet.CredentialProvider /// Gets a value that indicates if the credential provider should show a generic tile. That is, a tile that is not associated with a specific user. /// public abstract bool ShouldIncludeGenericTile(); - + + protected internal CredentialTile DefaultTile { get; set; } + + protected internal bool DefaultTileAutoLogon { get; set; } + + public void SetDefaultTile(CredentialTile tile, bool autoLogon) + { + if (this.DefaultTile == tile && this.DefaultTileAutoLogon == autoLogon) + { + return; + } + + if (!this.Tiles.Contains(tile)) + { + throw new InvalidOperationException("The default tile must be one of the tiles provided by the credential provider"); + } + + this.DefaultTile = tile; + this.DefaultTileAutoLogon = autoLogon; + this.ReloadUserTiles(); + } + /// /// Notifies LogonUI that one of more of the tile items has been modified, and should be reloaded /// diff --git a/src/Lithnet.CredentialProvider/CredentialTile.ICredentialProviderCredential.cs b/src/Lithnet.CredentialProvider/CredentialTile.ICredentialProviderCredential.cs index 7b858aa..90c348b 100644 --- a/src/Lithnet.CredentialProvider/CredentialTile.ICredentialProviderCredential.cs +++ b/src/Lithnet.CredentialProvider/CredentialTile.ICredentialProviderCredential.cs @@ -66,8 +66,8 @@ namespace Lithnet.CredentialProvider { this.logger.LogTrace("SetSelected"); this.IsSelected = true; - this.OnSelected(out bool autoLogon); - pbAutoLogon = autoLogon ? 1 : 0; + this.OnSelected(); + pbAutoLogon = this.ShouldAutoLogon() ? 1 : 0; return HRESULT.S_OK; } catch (Exception ex) diff --git a/src/Lithnet.CredentialProvider/CredentialTile.cs b/src/Lithnet.CredentialProvider/CredentialTile.cs index 9290143..28d652c 100644 --- a/src/Lithnet.CredentialProvider/CredentialTile.cs +++ b/src/Lithnet.CredentialProvider/CredentialTile.cs @@ -40,19 +40,16 @@ namespace Lithnet.CredentialProvider /// public bool IsAutoLogon { - get => this.isAutoLogon; - set - { - this.isAutoLogon = value; - this.CredentialProvider.ReloadUserTiles(); - - } + get => this.CredentialProvider.DefaultTile == this && this.CredentialProvider.DefaultTileAutoLogon; } /// - /// Gets a value indicating if this should be the default time + /// Gets a value indicating if this should be the default tile /// - public bool IsDefault { get; set; } + public bool IsDefault + { + get => this.CredentialProvider.DefaultTile == this; + } /// /// Gets the current usage scenario @@ -164,14 +161,16 @@ namespace Lithnet.CredentialProvider /// /// Called when the user selects this tile /// - /// A value that indicates if logon should be performed immediately, without waiting for further user input + protected virtual void OnSelected() { } + + /// + /// Called after a tiles is selected to determine if the user should be automatically logged on + /// + /// True, if a logon should be immediately attempted /// /// In Windows 10, if a credential provider wants to automatically log the user on in a situation Windows does not think is appropriate, the system will display a sign in button as a speed bump. One example of this is when a user with an empty password locks the computer or signs out. In that scenario, Windows does not directly log the user back in. /// - protected virtual void OnSelected(out bool autoLogon) - { - autoLogon = false; - } + protected virtual bool ShouldAutoLogon() => false; /// /// Called when a user deselects this tile