diff --git a/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIData.cs b/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIData.cs
index 6c56ae8..de92d28 100644
--- a/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIData.cs
+++ b/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIData.cs
@@ -34,14 +34,25 @@ namespace Lithnet.CredentialProvider
///
/// Gets a value indicating the consent prompt type
///
- public int PromptType => this.header.PromptType;
+ public ConsentUIPromptType PromptType => this.header.PromptType;
///
/// Gets a handle to the Window that was responsible for invoking the ConsentUI prompt
///
- public IntPtr HWnd => this.header.hWnd;
+ public IntPtr HWnd => this.header.hWindow;
- public ElevationType ElevationType => this.header.elevationType;
+ ///
+ /// Gets the method that ConsentUI has been told to fetch approval.
+ /// In the case where a Credential Provider is initialised, this should always be `Credentials`.
+ ///
+ public ConsentUIElevationType ElevationType => this.header.ElevationType;
+
+ ///
+ /// A series of flags that AppInfo passes to ConsentUI to signifiy actions that need to
+ /// take place on the UI side.
+ /// This includes specifics around the UI that should be presented & signature verification settings.
+ ///
+ public ConsentUIFlags Flags => this.header.Flags;
///
/// Gets the ID of the session where the ConsentUI prompt was originally invoked
diff --git a/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataExe.cs b/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataExe.cs
index 4d74baa..7a90c44 100644
--- a/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataExe.cs
+++ b/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataExe.cs
@@ -9,6 +9,9 @@ namespace Lithnet.CredentialProvider
///
public class ConsentUIDataExe : ConsentUIData
{
+ ///
+ /// A file handle pointing to the EXE in question
+ ///
private IntPtr hFile;
///
diff --git a/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataMsi.cs b/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataMsi.cs
index 930412b..436999d 100644
--- a/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataMsi.cs
+++ b/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataMsi.cs
@@ -9,6 +9,11 @@ namespace Lithnet.CredentialProvider
///
public class ConsentUIDataMsi : ConsentUIData
{
+ ///
+ /// The action being performed, such as Install, Uninstall or Repair
+ ///
+ public ConsentUIMsiAction Action { get; set; }
+
///
/// The name of the product being installed
///
@@ -39,16 +44,6 @@ namespace Lithnet.CredentialProvider
///
public string OriginalMsi { get; }
- ///
- /// A currently unknown parameter
- ///
- public string Unknown1 { get; }
-
- ///
- /// A currently unknown parameter
- ///
- public string Unknown2 { get; }
-
internal ConsentUIDataMsi(IntPtr pData, int expectedSize) : base(pData, expectedSize)
{
if (this.header.Type != ConsentUIType.Msi)
@@ -58,14 +53,13 @@ namespace Lithnet.CredentialProvider
var s = Marshal.PtrToStructure(pData);
+ this.Action = s.MsiAction;
this.ProductName = this.GetStringValueIfValid(pData, (int)s.oProductName);
this.Version = this.GetStringValueIfValid(pData, (int)s.oVersion);
this.Locale = this.GetStringValueIfValid(pData, (int)s.oLocale);
this.Publisher = this.GetStringValueIfValid(pData, (int)s.oPublisher);
- this.ExecutionPath = this.GetStringValueIfValid(pData, (int)s.oExecutionPath);
- this.OriginalMsi = this.GetStringValueIfValid(pData, (int)s.oOriginalMsi);
- this.Unknown1 = this.GetStringValueIfValid(pData, (int)s.oUnknown1);
- this.Unknown2 = this.GetStringValueIfValid(pData, (int)s.oUnknown2);
+ this.ExecutionPath = this.GetStringValueIfValid(pData, (int)s.oExecutionPath);
+ this.OriginalMsi = this.GetStringValueIfValid(pData, (int)s.oOriginalMsi);
}
}
}
diff --git a/src/Lithnet.CredentialProvider/Enums/ConsentUIElevationType.cs b/src/Lithnet.CredentialProvider/Enums/ConsentUIElevationType.cs
new file mode 100644
index 0000000..b01808b
--- /dev/null
+++ b/src/Lithnet.CredentialProvider/Enums/ConsentUIElevationType.cs
@@ -0,0 +1,24 @@
+namespace Lithnet.CredentialProvider
+{
+ public enum ConsentUIElevationType
+ {
+ Unknown = 0,
+
+ ///
+ /// Automatic Admin Mode.
+ /// This seems to be an instance where UAC creates a local, secondary
+ /// account called '%username%_admin' which is used to elevate a process.
+ ///
+ AutomaticAdmin = 1,
+
+ ///
+ /// Prompt the user for consent (i.e. Yes or No)
+ ///
+ Consent = 2,
+
+ ///
+ /// Prompt the user for credentials
+ ///
+ Credentials = 3
+ }
+}
\ No newline at end of file
diff --git a/src/Lithnet.CredentialProvider/Enums/ConsentUIFlags.cs b/src/Lithnet.CredentialProvider/Enums/ConsentUIFlags.cs
new file mode 100644
index 0000000..08bda47
--- /dev/null
+++ b/src/Lithnet.CredentialProvider/Enums/ConsentUIFlags.cs
@@ -0,0 +1,71 @@
+using System;
+
+namespace Lithnet.CredentialProvider
+{
+ [Flags]
+ public enum ConsentUIFlags
+ {
+ SkipSignatureVerification = 0x01,
+
+ ///
+ /// Indicates to ConsentUI that it needs to switch to the Secure Desktop
+ ///
+ SecureDesktop = 0x02,
+
+ Unknown1 = 0x04,
+ Unknown2 = 0x08,
+ Unknown3 = 0x10,
+
+ ///
+ /// This flag seems to cause ConsentUI to
+ /// skip all signature verification related code.
+ ///
+ SkipVerification = 0x20,
+
+ ///
+ /// Indicates that the executable file is contained within a Windows directory.
+ /// As all the executables in System32, etc. are unsigned, ConsentUI
+ /// uses this to toggle catalog verification, if required.
+ ///
+ InWindowsDirectory = 0x40,
+
+ ///
+ /// Seems to indicates to ConsentUI that automatic elevation should occur,
+ /// and that the executable is in a safe Windows location
+ ///
+ AutoElevationWindows = 0x80,
+
+ ///
+ /// Like `AutoElevationWindows`, this seems indicates to ConsentUI that
+ /// automatic elevation should occur, but that further verification
+ /// inside ConsentUI should occur.
+ ///
+ AutoElevationOther = 0x100,
+
+ Unknown4 = 0x200,
+
+ ///
+ /// ConsentUI uses this flag to determine if it should pass
+ /// SIF_BASE_VERIFICATION | SIF_AUTHENTICODE_SIGNED to WTGetSignatureInfo
+ ///
+ PerformBaseVerification = 0x400,
+
+ ///
+ /// Indicates that the publisher is untrusted - this is what seems to trigger
+ /// an AMSI scan (i.e., SmartScreen)
+ ///
+ UntrustedPublisher = 0x800,
+
+ ///
+ /// This flag seems to cause ConsentUI to skip all elevation-related code and exit.
+ ///
+ BlockElevation = 0x1000,
+
+ ///
+ /// Corresponds to `ConsentUIElevationType.AutomaticAdmin`
+ /// This seems to be an instance where UAC creates a local, secondary
+ /// account called '%username%_admin' which is used to elevate a process.
+ ///
+ AutomaticAdminMode = 0x2000
+ }
+}
diff --git a/src/Lithnet.CredentialProvider/Enums/ConsentUIMsiAction.cs b/src/Lithnet.CredentialProvider/Enums/ConsentUIMsiAction.cs
new file mode 100644
index 0000000..24e7ad1
--- /dev/null
+++ b/src/Lithnet.CredentialProvider/Enums/ConsentUIMsiAction.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace Lithnet.CredentialProvider
+{
+ public enum ConsentUIMsiAction : uint
+ {
+ Install = 0,
+ Uninstall = 1,
+ Update = 2
+ }
+}
diff --git a/src/Lithnet.CredentialProvider/ConsentUI/ElevationType.cs b/src/Lithnet.CredentialProvider/Enums/ConsentUIPromptType.cs
similarity index 53%
rename from src/Lithnet.CredentialProvider/ConsentUI/ElevationType.cs
rename to src/Lithnet.CredentialProvider/Enums/ConsentUIPromptType.cs
index 39770de..eee927a 100644
--- a/src/Lithnet.CredentialProvider/ConsentUI/ElevationType.cs
+++ b/src/Lithnet.CredentialProvider/Enums/ConsentUIPromptType.cs
@@ -1,10 +1,10 @@
namespace Lithnet.CredentialProvider
{
- public enum ElevationType
+ public enum ConsentUIPromptType
{
- Unknown1 = 0,
- Unknown2 = 1,
+ Unknown = 0,
+ AutomaticAdmin = 1,
Consent = 2,
Credentials = 3
}
-}
\ No newline at end of file
+}
diff --git a/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeader.cs b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeader.cs
index e84af60..f016be1 100644
--- a/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeader.cs
+++ b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeader.cs
@@ -8,24 +8,24 @@ namespace Lithnet.CredentialProvider.Interop
{
public int Size; // 4
public ConsentUIType Type; // 4
- public int PromptType; // 4
+ public ConsentUIPromptType PromptType; // 4
// padding on x64 - 4
// 16
- public IntPtr hWnd; // 8
+ public IntPtr hWindow; // 8
public IntPtr hToken; // 8
// 32
- public ElevationType elevationType; // 4
+ public ConsentUIElevationType ElevationType; // 4
public int sessionId; // 4
public IntPtr hMutex; // 8
// 48+
- public int unknownFlags1; // 4
- public int unknownFlags2; // 4
+ public ConsentUIFlags Flags; // 4
+ public int unknown0; // 4
public IntPtr pReturnAddress; // 8
// 64
diff --git a/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureMsi.cs b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureMsi.cs
index 85b7ab3..b7a04bc 100644
--- a/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureMsi.cs
+++ b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureMsi.cs
@@ -10,7 +10,7 @@ namespace Lithnet.CredentialProvider.Interop
// 64
- public IntPtr hUnknown1; // 8
+ public ConsentUIMsiAction MsiAction; // 8
public IntPtr oProductName; // 8
// 64 + 16 == 80