diff --git a/src/Lithnet.CredentialProvider.UnitTests.x64/Helpers.cs b/src/Lithnet.CredentialProvider.UnitTests.x64/Helpers.cs new file mode 100644 index 0000000..4b7328e --- /dev/null +++ b/src/Lithnet.CredentialProvider.UnitTests.x64/Helpers.cs @@ -0,0 +1,19 @@ +using System.IO; +using System.Runtime.InteropServices; +using Lithnet.CredentialProvider.Interop; +using NUnit.Framework; + +namespace Lithnet.CredentialProvider.UnitTests +{ + internal static class Helpers + { + public static SafeHGlobalHandle ReadFile(string filename) + { + var data = File.ReadAllBytes(Path.Combine(TestContext.CurrentContext.TestDirectory, filename)); + var p = SafeHGlobalHandle.AllocHGlobal(data.Length); + Marshal.Copy(data, 0, p.ToIntPtr(), data.Length); + + return p; + } + } +} diff --git a/src/Lithnet.CredentialProvider.UnitTests.x64/Lithnet.CredentialProvider.UnitTests.x64.csproj b/src/Lithnet.CredentialProvider.UnitTests.x64/Lithnet.CredentialProvider.UnitTests.x64.csproj new file mode 100644 index 0000000..86fc565 --- /dev/null +++ b/src/Lithnet.CredentialProvider.UnitTests.x64/Lithnet.CredentialProvider.UnitTests.x64.csproj @@ -0,0 +1,25 @@ + + + + net6.0-windows;net7.0-windows;net8.0-windows;net461;net48 + false + x64 + + + + + + + + + + + + + + + PreserveNewest + + + + diff --git a/src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-com-x64.dat b/src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V1/dump-consent-com-x64.dat similarity index 100% rename from src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-com-x64.dat rename to src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V1/dump-consent-com-x64.dat diff --git a/src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-exe-x64.dat b/src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V1/dump-consent-exe-x64.dat similarity index 100% rename from src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-exe-x64.dat rename to src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V1/dump-consent-exe-x64.dat diff --git a/src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-msi-x64.dat b/src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V1/dump-consent-msi-x64.dat similarity index 100% rename from src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-msi-x64.dat rename to src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V1/dump-consent-msi-x64.dat diff --git a/src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-msix-x64.dat b/src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V1/dump-consent-msix-x64.dat similarity index 100% rename from src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-msix-x64.dat rename to src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V1/dump-consent-msix-x64.dat diff --git a/src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V2/dump-consent-com-x64.dat b/src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V2/dump-consent-com-x64.dat new file mode 100644 index 0000000..ad14352 Binary files /dev/null and b/src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V2/dump-consent-com-x64.dat differ diff --git a/src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V2/dump-consent-exe-x64.dat b/src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V2/dump-consent-exe-x64.dat new file mode 100644 index 0000000..e250d05 Binary files /dev/null and b/src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V2/dump-consent-exe-x64.dat differ diff --git a/src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V2/dump-consent-msi-x64.dat b/src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V2/dump-consent-msi-x64.dat new file mode 100644 index 0000000..64c404d Binary files /dev/null and b/src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V2/dump-consent-msi-x64.dat differ diff --git a/src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V2/dump-consent-msix-x64.dat b/src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V2/dump-consent-msix-x64.dat new file mode 100644 index 0000000..e7687e9 Binary files /dev/null and b/src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V2/dump-consent-msix-x64.dat differ diff --git a/src/Lithnet.CredentialProvider.UnitTests.x64/V1HeaderTests.cs b/src/Lithnet.CredentialProvider.UnitTests.x64/V1HeaderTests.cs new file mode 100644 index 0000000..abf486c --- /dev/null +++ b/src/Lithnet.CredentialProvider.UnitTests.x64/V1HeaderTests.cs @@ -0,0 +1,96 @@ +using System; +using Lithnet.CredentialProvider.Interop; +using NUnit.Framework; + +namespace Lithnet.CredentialProvider.UnitTests +{ + public class V1HeaderTests + { + [SetUp] + public void Setup() + { + ConsentUIData.HeaderSize = ConsentUIData.v1HeaderSize; + } + + [Test] + public void TestExe() + { + SafeHGlobalHandle p = Helpers.ReadFile($"Samples\\V1\\dump-consent-exe-x64.dat"); + + var d = new ConsentUIDataExe(p.ToIntPtr(), p.Size); + + Assert.AreEqual(ConsentUIType.Exe, d.Type); + Assert.AreEqual(ConsentUIFlags.InWindowsDirectory | ConsentUIFlags.SecureDesktop | ConsentUIFlags.Unknown3, d.Flags); + Assert.AreEqual(3, d.SessionId); + Assert.AreEqual((IntPtr)0x0000000000010128, d.HWnd); + Assert.AreEqual(ConsentUIElevationReason.Request, d.ElevationReason); + Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); + Assert.AreEqual("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", d.ExecutablePath); + Assert.AreEqual("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", d.Unknown1); + Assert.AreEqual("\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" ARGS1 ARGS2", d.CommandLine); + Assert.AreEqual("", d.Unknown2); + } + + [Test] + public void TestMsi() + { + SafeHGlobalHandle p = Helpers.ReadFile($"Samples\\V1\\dump-consent-msi-x64.dat"); + + var d = new ConsentUIDataMsi(p.ToIntPtr(), p.Size); + + Assert.AreEqual(ConsentUIType.Msi, d.Type); + Assert.AreEqual(ConsentUIFlags.InWindowsDirectory | ConsentUIFlags.SecureDesktop | ConsentUIFlags.AutoElevationOther, d.Flags); + Assert.AreEqual(3, d.SessionId); + Assert.AreEqual((IntPtr)0x0000000000230370, d.HWnd); + Assert.AreEqual(ConsentUIElevationReason.Msi, d.ElevationReason); + Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); + Assert.AreEqual("7-Zip 23.01 (x64 edition)", d.ProductName); + Assert.AreEqual(ConsentUIMsiAction.Install, d.Action); + Assert.AreEqual("C:\\Windows\\Installer\\b733392.msi", d.ExecutionPath); + Assert.AreEqual("1033", d.Locale); + Assert.AreEqual("C:\\Users\\ryan2\\Downloads\\7z2301-x64.msi", d.OriginalMsi); + Assert.AreEqual("7-Zip 23.01 (x64 edition)", d.ProductName); + Assert.AreEqual("Igor Pavlov", d.Publisher); + Assert.AreEqual("23.01.00.0", d.Version); + } + + [Test] + public void TestMsix() + { + SafeHGlobalHandle p = Helpers.ReadFile($"Samples\\V1\\dump-consent-msix-x64.dat"); + + var d = new ConsentUIDataMsix(p.ToIntPtr(), p.Size); + + Assert.AreEqual(ConsentUIType.Msix, d.Type); + Assert.AreEqual( ConsentUIFlags.SecureDesktop | ConsentUIFlags.Unknown3, d.Flags); + Assert.AreEqual(3, d.SessionId); + Assert.AreEqual((IntPtr)0x0, d.HWnd); + Assert.AreEqual(ConsentUIElevationReason.Msix, d.ElevationReason); + Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); + Assert.AreEqual("\"C:\\Program Files\\WindowsApps\\Microsoft.MSIXPackagingTool_1.2023.807.0_x64__8wekyb3d8bbwe\\MsixPackageTool.exe\" ", d.CommandLine); + Assert.AreEqual("C:\\Program Files\\WindowsApps\\Microsoft.MSIXPackagingTool_1.2023.807.0_x64__8wekyb3d8bbwe\\MsixPackageTool.exe", d.ExecutablePath); + Assert.AreEqual("Microsoft.MSIXPackagingTool_8wekyb3d8bbwe!Msix.App", d.OtherName); + Assert.AreEqual("Microsoft.MSIXPackagingTool_8wekyb3d8bbwe", d.PackageName); + } + + [Test] + public void TestCom() + { + SafeHGlobalHandle p = Helpers.ReadFile($"Samples\\V1\\dump-consent-com-x64.dat"); + + var d = new ConsentUIDataCom(p.ToIntPtr(), p.Size); + + Assert.AreEqual(ConsentUIType.Com, d.Type); + Assert.AreEqual(ConsentUIFlags.SecureDesktop | ConsentUIFlags.AutoElevationOther | ConsentUIFlags.InWindowsDirectory, d.Flags); + Assert.AreEqual(3, d.SessionId); + Assert.AreEqual((IntPtr)0x00000000000903c2, d.HWnd); + Assert.AreEqual(ConsentUIElevationReason.Clsid, d.ElevationReason); + Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); + Assert.AreEqual(new Guid("{3ad05575-8857-4850-9277-11b85bdb8e09}"), d.ClsId); + Assert.AreEqual("C:\\Windows\\system32\\windows.storage.dll", d.ComComponentPath); + Assert.AreEqual("", d.ImageResourcePath); + Assert.AreEqual("File Operation", d.OperationType); + Assert.AreEqual("C:\\Windows\\Explorer.EXE", d.ProcessPath); + } + } +} \ No newline at end of file diff --git a/src/Lithnet.CredentialProvider.UnitTests.x64/V2HeaderTests.cs b/src/Lithnet.CredentialProvider.UnitTests.x64/V2HeaderTests.cs new file mode 100644 index 0000000..d32e3f3 --- /dev/null +++ b/src/Lithnet.CredentialProvider.UnitTests.x64/V2HeaderTests.cs @@ -0,0 +1,97 @@ +using System; +using Lithnet.CredentialProvider.Interop; +using NUnit.Framework; + +namespace Lithnet.CredentialProvider.UnitTests +{ + public class V2HeaderTests + { + + [SetUp] + public void Setup() + { + ConsentUIData.HeaderSize = ConsentUIData.v2HeaderSize; + } + + [Test] + public void TestExe() + { + SafeHGlobalHandle p = Helpers.ReadFile($"Samples\\V2\\dump-consent-exe-x64.dat"); + + ConsentUIDataExe d = new ConsentUIDataExe(p.ToIntPtr(), p.Size); + + Assert.AreEqual(ConsentUIType.Exe, d.Type); + Assert.AreEqual(ConsentUIFlags.InWindowsDirectory | ConsentUIFlags.SecureDesktop | ConsentUIFlags.Unknown3, d.Flags); + Assert.AreEqual(3, d.SessionId); + Assert.AreEqual((IntPtr)0x0, d.HWnd); // this seems odd + Assert.AreEqual(ConsentUIElevationReason.Request, d.ElevationReason); + Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); + Assert.AreEqual("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", d.ExecutablePath); + Assert.AreEqual("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", d.Unknown1); + Assert.AreEqual("\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" ", d.CommandLine); + Assert.AreEqual("", d.Unknown2); + } + + [Test] + public void TestMsi() + { + SafeHGlobalHandle p = Helpers.ReadFile($"Samples\\V2\\dump-consent-msi-x64.dat"); + + var d = new ConsentUIDataMsi(p.ToIntPtr(), p.Size); + + Assert.AreEqual(ConsentUIType.Msi, d.Type); + Assert.AreEqual(ConsentUIFlags.InWindowsDirectory | ConsentUIFlags.SecureDesktop | ConsentUIFlags.AutoElevationOther, d.Flags); + Assert.AreEqual(2, d.SessionId); + Assert.AreEqual((IntPtr)0x00000000001e033a, d.HWnd); + Assert.AreEqual(ConsentUIElevationReason.Msi, d.ElevationReason); + Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); + Assert.AreEqual("7-Zip 24.08 (x64 edition)", d.ProductName); + Assert.AreEqual(ConsentUIMsiAction.Install, d.Action); + Assert.AreEqual("C:\\WINDOWS\\Installer\\58ca98.msi", d.ExecutionPath); + Assert.AreEqual("1033", d.Locale); + Assert.AreEqual("C:\\Users\\testuser\\Downloads\\7z2408-x64.msi", d.OriginalMsi); + Assert.AreEqual("7-Zip 24.08 (x64 edition)", d.ProductName); + Assert.AreEqual("Igor Pavlov", d.Publisher); + Assert.AreEqual("24.08.00.0", d.Version); + } + + [Test] + public void TestMsix() + { + SafeHGlobalHandle p = Helpers.ReadFile($"Samples\\V2\\dump-consent-msix-x64.dat"); + + var d = new ConsentUIDataMsix(p.ToIntPtr(), p.Size); + + Assert.AreEqual(ConsentUIType.Msix, d.Type); + Assert.AreEqual(ConsentUIFlags.SecureDesktop | ConsentUIFlags.Unknown3, d.Flags); + Assert.AreEqual(2, d.SessionId); + Assert.AreEqual((IntPtr)0x0, d.HWnd); + Assert.AreEqual(ConsentUIElevationReason.Msix, d.ElevationReason); + Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); + Assert.AreEqual("\"C:\\Program Files\\WindowsApps\\Microsoft.MSIXPackagingTool_1.2024.405.0_x64__8wekyb3d8bbwe\\MsixPackageTool.exe\" ", d.CommandLine); + Assert.AreEqual("C:\\Program Files\\WindowsApps\\Microsoft.MSIXPackagingTool_1.2024.405.0_x64__8wekyb3d8bbwe\\MsixPackageTool.exe", d.ExecutablePath); + Assert.AreEqual("Microsoft.MSIXPackagingTool_8wekyb3d8bbwe!Msix.App", d.OtherName); + Assert.AreEqual("Microsoft.MSIXPackagingTool_8wekyb3d8bbwe", d.PackageName); + } + + [Test] + public void TestCom() + { + SafeHGlobalHandle p = Helpers.ReadFile($"Samples\\V2\\dump-consent-com-x64.dat"); + + var d = new ConsentUIDataCom(p.ToIntPtr(), p.Size); + + Assert.AreEqual(ConsentUIType.Com, d.Type); + Assert.AreEqual(ConsentUIFlags.SecureDesktop | ConsentUIFlags.AutoElevationOther | ConsentUIFlags.InWindowsDirectory, d.Flags); + Assert.AreEqual(2, d.SessionId); + Assert.AreEqual((IntPtr)0x00000000000d021e, d.HWnd); + Assert.AreEqual(ConsentUIElevationReason.Clsid, d.ElevationReason); + Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); + Assert.AreEqual(new Guid("{3ad05575-8857-4850-9277-11b85bdb8e09}"), d.ClsId); + Assert.AreEqual("C:\\WINDOWS\\system32\\windows.storage.dll", d.ComComponentPath); + Assert.AreEqual("", d.ImageResourcePath); + Assert.AreEqual("File Operation", d.OperationType); + Assert.AreEqual("C:\\WINDOWS\\Explorer.EXE", d.ProcessPath); + } + } +} \ No newline at end of file diff --git a/src/Lithnet.CredentialProvider.UnitTests.x86/Helpers.cs b/src/Lithnet.CredentialProvider.UnitTests.x86/Helpers.cs new file mode 100644 index 0000000..4b7328e --- /dev/null +++ b/src/Lithnet.CredentialProvider.UnitTests.x86/Helpers.cs @@ -0,0 +1,19 @@ +using System.IO; +using System.Runtime.InteropServices; +using Lithnet.CredentialProvider.Interop; +using NUnit.Framework; + +namespace Lithnet.CredentialProvider.UnitTests +{ + internal static class Helpers + { + public static SafeHGlobalHandle ReadFile(string filename) + { + var data = File.ReadAllBytes(Path.Combine(TestContext.CurrentContext.TestDirectory, filename)); + var p = SafeHGlobalHandle.AllocHGlobal(data.Length); + Marshal.Copy(data, 0, p.ToIntPtr(), data.Length); + + return p; + } + } +} diff --git a/src/Lithnet.CredentialProvider.UnitTests.x86/Lithnet.CredentialProvider.UnitTests.x86.csproj b/src/Lithnet.CredentialProvider.UnitTests.x86/Lithnet.CredentialProvider.UnitTests.x86.csproj new file mode 100644 index 0000000..31f57a7 --- /dev/null +++ b/src/Lithnet.CredentialProvider.UnitTests.x86/Lithnet.CredentialProvider.UnitTests.x86.csproj @@ -0,0 +1,25 @@ + + + + net6.0-windows;net7.0-windows;net8.0-windows;net461;net48 + false + x86 + + + + + + + + + + + + + + + PreserveNewest + + + + diff --git a/src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-com-x86.dat b/src/Lithnet.CredentialProvider.UnitTests.x86/Samples/V1/dump-consent-com-x86.dat similarity index 100% rename from src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-com-x86.dat rename to src/Lithnet.CredentialProvider.UnitTests.x86/Samples/V1/dump-consent-com-x86.dat diff --git a/src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-exe-x86.dat b/src/Lithnet.CredentialProvider.UnitTests.x86/Samples/V1/dump-consent-exe-x86.dat similarity index 100% rename from src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-exe-x86.dat rename to src/Lithnet.CredentialProvider.UnitTests.x86/Samples/V1/dump-consent-exe-x86.dat diff --git a/src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-msi-x86.dat b/src/Lithnet.CredentialProvider.UnitTests.x86/Samples/V1/dump-consent-msi-x86.dat similarity index 100% rename from src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-msi-x86.dat rename to src/Lithnet.CredentialProvider.UnitTests.x86/Samples/V1/dump-consent-msi-x86.dat diff --git a/src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-msix-x86.dat b/src/Lithnet.CredentialProvider.UnitTests.x86/Samples/V1/dump-consent-msix-x86.dat similarity index 100% rename from src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-msix-x86.dat rename to src/Lithnet.CredentialProvider.UnitTests.x86/Samples/V1/dump-consent-msix-x86.dat diff --git a/src/Lithnet.CredentialProvider.UnitTests.x86/V1HeaderTests.cs b/src/Lithnet.CredentialProvider.UnitTests.x86/V1HeaderTests.cs new file mode 100644 index 0000000..b2ad989 --- /dev/null +++ b/src/Lithnet.CredentialProvider.UnitTests.x86/V1HeaderTests.cs @@ -0,0 +1,96 @@ +using System; +using Lithnet.CredentialProvider.Interop; +using NUnit.Framework; + +namespace Lithnet.CredentialProvider.UnitTests +{ + public class V1HeaderTests + { + [SetUp] + public void Setup() + { + ConsentUIData.HeaderSize = ConsentUIData.v1HeaderSize; + } + + [Test] + public void TestExe() + { + SafeHGlobalHandle p = Helpers.ReadFile($"Samples\\V1\\dump-consent-exe-x86.dat"); + + var d = new ConsentUIDataExe(p.ToIntPtr(), p.Size); + + Assert.AreEqual(ConsentUIType.Exe, d.Type); + Assert.AreEqual(ConsentUIFlags.InWindowsDirectory | ConsentUIFlags.SecureDesktop | ConsentUIFlags.Unknown3, d.Flags); + Assert.AreEqual(2, d.SessionId); + Assert.AreEqual((IntPtr)0x0006056a, d.HWnd); + Assert.AreEqual(ConsentUIElevationReason.Request, d.ElevationReason); + Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); + Assert.AreEqual("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", d.ExecutablePath); + Assert.AreEqual("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", d.Unknown1); + Assert.AreEqual("\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" ARGS1 ARGS2", d.CommandLine); + Assert.AreEqual("", d.Unknown2); + } + + [Test] + public void TestMsi() + { + SafeHGlobalHandle p = Helpers.ReadFile($"Samples\\V1\\dump-consent-msi-x86.dat"); + + var d = new ConsentUIDataMsi(p.ToIntPtr(), p.Size); + + Assert.AreEqual(ConsentUIType.Msi, d.Type); + Assert.AreEqual(ConsentUIFlags.InWindowsDirectory | ConsentUIFlags.SecureDesktop | ConsentUIFlags.AutoElevationOther, d.Flags); + Assert.AreEqual(2, d.SessionId); + Assert.AreEqual((IntPtr)0x000705bc, d.HWnd); + Assert.AreEqual(ConsentUIElevationReason.Msi, d.ElevationReason); + Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); + Assert.AreEqual("7-Zip 23.01", d.ProductName); + Assert.AreEqual(ConsentUIMsiAction.Install, d.Action); + Assert.AreEqual("C:\\Windows\\Installer\\26396d5.msi", d.ExecutionPath); + Assert.AreEqual("1033", d.Locale); + Assert.AreEqual("C:\\Users\\std\\Downloads\\7z2301.msi", d.OriginalMsi); + Assert.AreEqual("7-Zip 23.01", d.ProductName); + Assert.AreEqual("Igor Pavlov", d.Publisher); + Assert.AreEqual("23.01.00.0", d.Version); + } + + [Test] + public void TestMsix() + { + SafeHGlobalHandle p = Helpers.ReadFile($"Samples\\V1\\dump-consent-msix-x86.dat"); + + var d = new ConsentUIDataMsix(p.ToIntPtr(), p.Size); + + Assert.AreEqual(ConsentUIType.Msix, d.Type); + Assert.AreEqual( ConsentUIFlags.SecureDesktop | ConsentUIFlags.Unknown3, d.Flags); + Assert.AreEqual(2, d.SessionId); + Assert.AreEqual((IntPtr)0x0, d.HWnd); + Assert.AreEqual(ConsentUIElevationReason.Msix, d.ElevationReason); + Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); + Assert.AreEqual("\"C:\\Program Files\\WindowsApps\\Microsoft.MSIXPackagingTool_1.2023.807.0_x86__8wekyb3d8bbwe\\MsixPackageTool.exe\" ", d.CommandLine); + Assert.AreEqual("C:\\Program Files\\WindowsApps\\Microsoft.MSIXPackagingTool_1.2023.807.0_x86__8wekyb3d8bbwe\\MsixPackageTool.exe", d.ExecutablePath); + Assert.AreEqual("Microsoft.MSIXPackagingTool_8wekyb3d8bbwe!Msix.App", d.OtherName); + Assert.AreEqual("Microsoft.MSIXPackagingTool_8wekyb3d8bbwe", d.PackageName); + } + + [Test] + public void TestCom() + { + SafeHGlobalHandle p = Helpers.ReadFile($"Samples\\V1\\dump-consent-com-x86.dat"); + + var d = new ConsentUIDataCom(p.ToIntPtr(), p.Size); + + Assert.AreEqual(ConsentUIType.Com, d.Type); + Assert.AreEqual(ConsentUIFlags.SecureDesktop | ConsentUIFlags.AutoElevationOther | ConsentUIFlags.InWindowsDirectory, d.Flags); + Assert.AreEqual(2, d.SessionId); + Assert.AreEqual((IntPtr)0x000b0586, d.HWnd); + Assert.AreEqual(ConsentUIElevationReason.Clsid, d.ElevationReason); + Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); + Assert.AreEqual(new Guid("{3ad05575-8857-4850-9277-11b85bdb8e09}"), d.ClsId); + Assert.AreEqual("C:\\Windows\\system32\\windows.storage.dll", d.ComComponentPath); + Assert.AreEqual("", d.ImageResourcePath); + Assert.AreEqual("File Operation", d.OperationType); + Assert.AreEqual("C:\\Windows\\Explorer.EXE", d.ProcessPath); + } + } +} \ No newline at end of file diff --git a/src/Lithnet.CredentialProvider.sln b/src/Lithnet.CredentialProvider.sln index 52e6520..4460844 100644 --- a/src/Lithnet.CredentialProvider.sln +++ b/src/Lithnet.CredentialProvider.sln @@ -23,6 +23,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lithnet.CredentialProvider. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lithnet.CredentialProvider.TestApp.x86", "samples\Lithnet.CredentialProvider.TestApp.x86\Lithnet.CredentialProvider.TestApp.x86.csproj", "{F39C84F2-60C2-45EB-BC87-0ED095D41C96}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lithnet.CredentialProvider.UnitTests.x64", "Lithnet.CredentialProvider.UnitTests.x64\Lithnet.CredentialProvider.UnitTests.x64.csproj", "{21E66D65-6E3F-4ACA-B1D0-CA4CC7C58D0C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lithnet.CredentialProvider.UnitTests.x86", "Lithnet.CredentialProvider.UnitTests.x86\Lithnet.CredentialProvider.UnitTests.x86.csproj", "{DA23151B-B7B6-4942-B7A4-48E1918EF145}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -57,6 +61,14 @@ Global {F39C84F2-60C2-45EB-BC87-0ED095D41C96}.Debug|Any CPU.Build.0 = Debug|Any CPU {F39C84F2-60C2-45EB-BC87-0ED095D41C96}.Release|Any CPU.ActiveCfg = Release|Any CPU {F39C84F2-60C2-45EB-BC87-0ED095D41C96}.Release|Any CPU.Build.0 = Release|Any CPU + {21E66D65-6E3F-4ACA-B1D0-CA4CC7C58D0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {21E66D65-6E3F-4ACA-B1D0-CA4CC7C58D0C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {21E66D65-6E3F-4ACA-B1D0-CA4CC7C58D0C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {21E66D65-6E3F-4ACA-B1D0-CA4CC7C58D0C}.Release|Any CPU.Build.0 = Release|Any CPU + {DA23151B-B7B6-4942-B7A4-48E1918EF145}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DA23151B-B7B6-4942-B7A4-48E1918EF145}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DA23151B-B7B6-4942-B7A4-48E1918EF145}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DA23151B-B7B6-4942-B7A4-48E1918EF145}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIData.cs b/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIData.cs index de92d28..34fe588 100644 --- a/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIData.cs +++ b/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIData.cs @@ -23,8 +23,12 @@ namespace Lithnet.CredentialProvider { private static bool? isConsentUI; private static ConsentUICommandLineArgs commandLineArgs; - private protected ConsentUIStructureHeader header; + private protected ConsentUIStructureHeaderBase header; private readonly byte[] rawData; + private static readonly Version v2HeaderOsVersion = new Version(10, 0, 26100, 0); + internal static int v2HeaderSize = Marshal.SizeOf(); + internal static int v1HeaderSize = Marshal.SizeOf(); + internal static int HeaderSize { get; set; } = Environment.OSVersion.Version >= v2HeaderOsVersion ? v2HeaderSize : v1HeaderSize; /// /// Gets a value indicating the type of ConsentUI data structure @@ -32,7 +36,8 @@ namespace Lithnet.CredentialProvider public ConsentUIType Type => this.header.Type; /// - /// Gets a value indicating the consent prompt type + /// Gets a value indicating how UAC has been told to fetch approval. + /// In the case where a Credential Provider is initialised, this should always be `Credentials`. /// public ConsentUIPromptType PromptType => this.header.PromptType; @@ -42,13 +47,13 @@ namespace Lithnet.CredentialProvider public IntPtr HWnd => this.header.hWindow; /// - /// 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`. + /// Gets the reason why `consent.exe` was started in the first place. In other words, + /// the type of action that led to an elevation request. /// - public ConsentUIElevationType ElevationType => this.header.ElevationType; + public ConsentUIElevationReason ElevationReason => this.header.ElevationReason; /// - /// A series of flags that AppInfo passes to ConsentUI to signifiy actions that need to + /// 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. /// @@ -62,12 +67,18 @@ namespace Lithnet.CredentialProvider private protected ConsentUIData(IntPtr pData, int expectedSize) { this.rawData = GetRawBytes(pData, expectedSize); - this.header = Marshal.PtrToStructure(pData); + + this.header = Marshal.PtrToStructure(pData); if (this.header.Size != expectedSize) { throw new InvalidDataException($"The size of the data structure {this.header.Size} does not match the expected size {expectedSize}"); } + + if (HeaderSize > this.header.Size) + { + throw new InvalidDataException($"The size of the data structure {this.header.Size} is less than the expected header size {HeaderSize}"); + } } /// @@ -330,7 +341,7 @@ namespace Lithnet.CredentialProvider /// The handle to duplicate /// A duplicated reference to the handle /// Thrown when the handle could not be duplicated - protected private static SafeHandle DuplicateHandleInternal(IntPtr handle) + private protected static SafeHandle DuplicateHandleInternal(IntPtr handle) { commandLineArgs ??= GetConsentUICommandLineArgs(); diff --git a/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataCom.cs b/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataCom.cs index c596f0e..bc6c29d 100644 --- a/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataCom.cs +++ b/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataCom.cs @@ -41,7 +41,7 @@ namespace Lithnet.CredentialProvider throw new InvalidOperationException("The data structure is not of type COM"); } - var s = Marshal.PtrToStructure(pData); + var s = Marshal.PtrToStructure(pData + HeaderSize); this.ComComponentPath = this.GetStringValueIfValid(pData, (int)s.oComComponentPath); this.ImageResourcePath = this.GetStringValueIfValid(pData, (int)s.oImageResourcePath); diff --git a/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataExe.cs b/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataExe.cs index 7a90c44..80cae5f 100644 --- a/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataExe.cs +++ b/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataExe.cs @@ -50,7 +50,7 @@ namespace Lithnet.CredentialProvider throw new InvalidOperationException("The data structure is not of type EXE"); } - var s = Marshal.PtrToStructure(pData); + var s = Marshal.PtrToStructure(pData + HeaderSize); this.hFile = s.hFile; this.ExecutablePath = this.GetStringValueIfValid(pData, (int)s.oExecutablePath1); diff --git a/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataMsi.cs b/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataMsi.cs index 436999d..1197f0d 100644 --- a/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataMsi.cs +++ b/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataMsi.cs @@ -51,7 +51,7 @@ namespace Lithnet.CredentialProvider throw new InvalidOperationException("The data structure is not of type MSI"); } - var s = Marshal.PtrToStructure(pData); + var s = Marshal.PtrToStructure(pData + HeaderSize); this.Action = s.MsiAction; this.ProductName = this.GetStringValueIfValid(pData, (int)s.oProductName); diff --git a/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataMsix.cs b/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataMsix.cs index d93e4ee..6589216 100644 --- a/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataMsix.cs +++ b/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataMsix.cs @@ -36,7 +36,7 @@ namespace Lithnet.CredentialProvider throw new InvalidOperationException("The data structure is not of type MSIX"); } - var s = Marshal.PtrToStructure(pData); + var s = Marshal.PtrToStructure(pData + HeaderSize); this.ExecutablePath = this.GetStringValueIfValid(pData, (int)s.oExecutablePath); this.PackageName = this.GetStringValueIfValid(pData, (int)s.oPackageName); diff --git a/src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-winsec-x86.dat b/src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-winsec-x86.dat deleted file mode 100644 index 311afd6..0000000 Binary files a/src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-winsec-x86.dat and /dev/null differ diff --git a/src/Lithnet.CredentialProvider/Enums/ConsentUIElevationReason.cs b/src/Lithnet.CredentialProvider/Enums/ConsentUIElevationReason.cs new file mode 100644 index 0000000..9c07c1e --- /dev/null +++ b/src/Lithnet.CredentialProvider/Enums/ConsentUIElevationReason.cs @@ -0,0 +1,89 @@ +namespace Lithnet.CredentialProvider +{ + public enum ConsentUIElevationReason + { + /// + /// Application Compatibility + /// e.g. "Run this program as an Administrator" explicitly configured + /// + /// > "The AppCompat database stores information in the application + /// > compatibility fix entries for an application." + /// + /// `ELEVATION_REASON.ELEVATION_REASON_APPCOMPAT_EXPLICIT (ole32.dll)` + /// + AppCompatExplicit = 0, + + /// + /// Application Compatibility + /// e.g. "Run this program as an Administrator" set via Windows heuristics + /// + /// > "The AppCompat database stores information in the application + /// > compatibility fix entries for an application." + /// + /// `ELEVATION_REASON.ELEVATION_REASON_APPCOMPAT_HEURISTIC (ole32.dll)` + /// + AppCompatHeuristic = 1, + + /// + /// Application manifest + /// > "The Fusion database stores information from application + /// > manifests that describe the applications. The manifest schema + /// > is updated to add a new requested execution level field." + /// See also: https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests#trustinfo + /// + /// `ELEVATION_REASON.ELEVATION_REASON_FUSION (ole32.dll)` + /// + Fusion = 2, + + /// + /// Automatically detected Windows Installer package (e.g. an EXE installer) + /// > "Installer detection detects setup files, which helps prevent installations + /// > from being run without the user's knowledge and consent." + /// + /// `ELEVATION_REASON.ELEVATION_REASON_INSTALLER (ole32.dll)` + /// + Installer = 3, + + /// + /// COM elevation action + /// + /// `ELEVATION_REASON.ELEVATION_REASON_CLSID (ole32.dll)` + /// + Clsid = 4, + + /// + /// Windows Installer package installation (MSI) + /// + /// `ELEVATION_REASON.ELEVATION_REASON_MSI (ole32.dll)` + /// + Msi = 5, + + /// + /// "Run as Administrator..." (e.g. manual UAC) + /// + /// `ELEVATION_REASON.ELEVATION_REASON_REQUEST (ole32.dll)` + /// + Request = 6, + + /// + /// ActiveX Installer Service (AXIS) + /// + /// `ELEVATION_REASON.ELEVATION_REASON_AXIS (ole32.dll)` + /// + Axis = 7, + + /// + /// Packaged Applications (MSIX / APPX) + /// + /// `ELEVATION_REASON.ELEVATION_REASON_PACKAGED_APP (ole32.dll)` + /// + Msix = 8, + + /// + /// Unknown + /// + /// `ELEVATION_REASON.ELEVATION_REASON_NUM_REASONS (ole32.dll)` + /// + NumReasons = 9, + } +} \ No newline at end of file diff --git a/src/Lithnet.CredentialProvider/Enums/ConsentUIElevationType.cs b/src/Lithnet.CredentialProvider/Enums/ConsentUIElevationType.cs deleted file mode 100644 index b01808b..0000000 --- a/src/Lithnet.CredentialProvider/Enums/ConsentUIElevationType.cs +++ /dev/null @@ -1,24 +0,0 @@ -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 index 08bda47..04a82bf 100644 --- a/src/Lithnet.CredentialProvider/Enums/ConsentUIFlags.cs +++ b/src/Lithnet.CredentialProvider/Enums/ConsentUIFlags.cs @@ -62,7 +62,7 @@ namespace Lithnet.CredentialProvider BlockElevation = 0x1000, /// - /// Corresponds to `ConsentUIElevationType.AutomaticAdmin` + /// Corresponds to `ConsentUIPromptType.AutomaticAdmin` /// This seems to be an instance where UAC creates a local, secondary /// account called '%username%_admin' which is used to elevate a process. /// diff --git a/src/Lithnet.CredentialProvider/Interop/SafeHGlobalHandle.cs b/src/Lithnet.CredentialProvider/Interop/SafeHGlobalHandle.cs index 7650635..80828d6 100644 --- a/src/Lithnet.CredentialProvider/Interop/SafeHGlobalHandle.cs +++ b/src/Lithnet.CredentialProvider/Interop/SafeHGlobalHandle.cs @@ -10,6 +10,8 @@ namespace Lithnet.CredentialProvider.Interop /// IntPtr pointer; + int size; + SafeHGlobalHandle() { this.pointer = IntPtr.Zero; @@ -25,6 +27,8 @@ namespace Lithnet.CredentialProvider.Interop this.Dispose(); } + public int Size => size; + public static SafeHGlobalHandle InvalidHandle => new SafeHGlobalHandle(IntPtr.Zero); /// @@ -58,6 +62,7 @@ namespace Lithnet.CredentialProvider.Interop SafeHGlobalHandle result = new SafeHGlobalHandle(); result.pointer = Marshal.AllocHGlobal(cb); + result.size = cb; return result; } } diff --git a/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureCom.cs b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureCom.cs index 24a35a3..6c28aaa 100644 --- a/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureCom.cs +++ b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureCom.cs @@ -6,8 +6,6 @@ namespace Lithnet.CredentialProvider.Interop [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] internal struct ConsentUIStructureCom { - public ConsentUIStructureHeader Header; - // 64 public IntPtr oOperationType; // 8 diff --git a/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureExe.cs b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureExe.cs index ed69888..ff0682e 100644 --- a/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureExe.cs +++ b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureExe.cs @@ -6,8 +6,6 @@ namespace Lithnet.CredentialProvider.Interop [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] internal struct ConsentUIStructureExe { - public ConsentUIStructureHeader Header; - // 64 public IntPtr hFile; // 8 diff --git a/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeader.cs b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeaderBase.cs similarity index 79% rename from src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeader.cs rename to src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeaderBase.cs index f016be1..2edb82c 100644 --- a/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeader.cs +++ b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeaderBase.cs @@ -4,7 +4,7 @@ using System.Runtime.InteropServices; namespace Lithnet.CredentialProvider.Interop { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - internal struct ConsentUIStructureHeader + internal struct ConsentUIStructureHeaderBase { public int Size; // 4 public ConsentUIType Type; // 4 @@ -18,7 +18,7 @@ namespace Lithnet.CredentialProvider.Interop // 32 - public ConsentUIElevationType ElevationType; // 4 + public ConsentUIElevationReason ElevationReason; // 4 public int sessionId; // 4 public IntPtr hMutex; // 8 @@ -26,8 +26,5 @@ namespace Lithnet.CredentialProvider.Interop public ConsentUIFlags Flags; // 4 public int unknown0; // 4 - public IntPtr pReturnAddress; // 8 - - // 64 } } diff --git a/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeaderV1.cs b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeaderV1.cs new file mode 100644 index 0000000..9d387ed --- /dev/null +++ b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeaderV1.cs @@ -0,0 +1,15 @@ +using System; +using System.Runtime.InteropServices; + +namespace Lithnet.CredentialProvider.Interop +{ + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + internal struct ConsentUIStructureHeaderV1 + { + public ConsentUIStructureHeaderBase BaseHeader; + + public IntPtr pReturnAddress; // 8 + + // 64 + } +} diff --git a/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeaderV2.cs b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeaderV2.cs new file mode 100644 index 0000000..4fae264 --- /dev/null +++ b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeaderV2.cs @@ -0,0 +1,16 @@ +using System; +using System.Runtime.InteropServices; + +namespace Lithnet.CredentialProvider.Interop +{ + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + internal struct ConsentUIStructureHeaderV2 + { + public ConsentUIStructureHeaderBase BaseHeader; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x81)] + public byte[] unknown1; + + public IntPtr pReturnAddress; // 8 + } +} \ No newline at end of file diff --git a/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureMsi.cs b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureMsi.cs index b7a04bc..3d3b543 100644 --- a/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureMsi.cs +++ b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureMsi.cs @@ -6,8 +6,6 @@ namespace Lithnet.CredentialProvider.Interop [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] internal struct ConsentUIStructureMsi { - public ConsentUIStructureHeader Header; - // 64 public ConsentUIMsiAction MsiAction; // 8 diff --git a/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureMsix.cs b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureMsix.cs index 456624a..c58c24d 100644 --- a/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureMsix.cs +++ b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureMsix.cs @@ -6,8 +6,6 @@ namespace Lithnet.CredentialProvider.Interop [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] internal struct ConsentUIStructureMsix { - public ConsentUIStructureHeader Header; - // 64 public IntPtr oExecutablePath; // 8 diff --git a/src/Lithnet.CredentialProvider/Lithnet.CredentialProvider.csproj b/src/Lithnet.CredentialProvider/Lithnet.CredentialProvider.csproj index 34d41dc..7dfebbb 100644 --- a/src/Lithnet.CredentialProvider/Lithnet.CredentialProvider.csproj +++ b/src/Lithnet.CredentialProvider/Lithnet.CredentialProvider.csproj @@ -1,6 +1,6 @@  - net6.0-windows;net7.0-windows;net461 + net6.0-windows;net7.0-windows;net8.0-windows;net461 false Library true @@ -38,6 +38,15 @@ true + + + <_Parameter1>Lithnet.CredentialProvider.UnitTests.x64 + + + <_Parameter1>Lithnet.CredentialProvider.UnitTests.x86 + + + all diff --git a/src/Lithnet.CredentialProvider/NativeMethods.json b/src/Lithnet.CredentialProvider/NativeMethods.json deleted file mode 100644 index 6d04a57..0000000 --- a/src/Lithnet.CredentialProvider/NativeMethods.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "$schema": "https://aka.ms/CsWin32.schema.json" -} \ No newline at end of file