From fcdd67bb0f641aedf2a1fb12092ef2ece053a78a Mon Sep 17 00:00:00 2001 From: Ryan Newington Date: Wed, 28 Aug 2024 01:29:34 +1000 Subject: [PATCH] Adds support for reading 'v2' consent ui headers --- .../Helpers.cs | 19 ++++ ...et.CredentialProvider.UnitTests.x64.csproj | 25 +++++ .../Samples/V1}/dump-consent-com-x64.dat | Bin .../Samples/V1}/dump-consent-exe-x64.dat | Bin .../Samples/V1}/dump-consent-msi-x64.dat | Bin .../Samples/V1}/dump-consent-msix-x64.dat | Bin .../Samples/V2/dump-consent-com-x64.dat | Bin 0 -> 408 bytes .../Samples/V2/dump-consent-exe-x64.dat | Bin 0 -> 604 bytes .../Samples/V2/dump-consent-msi-x64.dat | Bin 0 -> 538 bytes .../Samples/V2/dump-consent-msix-x64.dat | Bin 0 -> 868 bytes .../V1HeaderTests.cs | 96 +++++++++++++++++ .../V2HeaderTests.cs | 97 ++++++++++++++++++ .../Helpers.cs | 19 ++++ ...et.CredentialProvider.UnitTests.x86.csproj | 25 +++++ .../Samples/V1}/dump-consent-com-x86.dat | Bin .../Samples/V1}/dump-consent-exe-x86.dat | Bin .../Samples/V1}/dump-consent-msi-x86.dat | Bin .../Samples/V1}/dump-consent-msix-x86.dat | Bin .../V1HeaderTests.cs | 96 +++++++++++++++++ src/Lithnet.CredentialProvider.sln | 12 +++ .../ConsentUI/ConsentUIData.cs | 11 +- .../ConsentUI/ConsentUIDataCom.cs | 2 +- .../ConsentUI/ConsentUIDataExe.cs | 2 +- .../ConsentUI/ConsentUIDataMsi.cs | 2 +- .../ConsentUI/ConsentUIDataMsix.cs | 2 +- .../Samples/dump-consent-winsec-x86.dat | Bin 384 -> 0 bytes .../Interop/SafeHGlobalHandle.cs | 5 + .../Interop/Structs/ConsentUIStructureCom.cs | 2 - .../Interop/Structs/ConsentUIStructureExe.cs | 2 - ...der.cs => ConsentUIStructureHeaderBase.cs} | 5 +- .../Structs/ConsentUIStructureHeaderV1.cs | 15 +++ .../Structs/ConsentUIStructureHeaderV2.cs | 16 +++ .../Interop/Structs/ConsentUIStructureMsi.cs | 2 - .../Interop/Structs/ConsentUIStructureMsix.cs | 2 - .../Lithnet.CredentialProvider.csproj | 9 ++ .../NativeMethods.json | 3 - 36 files changed, 447 insertions(+), 22 deletions(-) create mode 100644 src/Lithnet.CredentialProvider.UnitTests.x64/Helpers.cs create mode 100644 src/Lithnet.CredentialProvider.UnitTests.x64/Lithnet.CredentialProvider.UnitTests.x64.csproj rename src/{Lithnet.CredentialProvider/ConsentUI/Samples => Lithnet.CredentialProvider.UnitTests.x64/Samples/V1}/dump-consent-com-x64.dat (100%) rename src/{Lithnet.CredentialProvider/ConsentUI/Samples => Lithnet.CredentialProvider.UnitTests.x64/Samples/V1}/dump-consent-exe-x64.dat (100%) rename src/{Lithnet.CredentialProvider/ConsentUI/Samples => Lithnet.CredentialProvider.UnitTests.x64/Samples/V1}/dump-consent-msi-x64.dat (100%) rename src/{Lithnet.CredentialProvider/ConsentUI/Samples => Lithnet.CredentialProvider.UnitTests.x64/Samples/V1}/dump-consent-msix-x64.dat (100%) create mode 100644 src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V2/dump-consent-com-x64.dat create mode 100644 src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V2/dump-consent-exe-x64.dat create mode 100644 src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V2/dump-consent-msi-x64.dat create mode 100644 src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V2/dump-consent-msix-x64.dat create mode 100644 src/Lithnet.CredentialProvider.UnitTests.x64/V1HeaderTests.cs create mode 100644 src/Lithnet.CredentialProvider.UnitTests.x64/V2HeaderTests.cs create mode 100644 src/Lithnet.CredentialProvider.UnitTests.x86/Helpers.cs create mode 100644 src/Lithnet.CredentialProvider.UnitTests.x86/Lithnet.CredentialProvider.UnitTests.x86.csproj rename src/{Lithnet.CredentialProvider/ConsentUI/Samples => Lithnet.CredentialProvider.UnitTests.x86/Samples/V1}/dump-consent-com-x86.dat (100%) rename src/{Lithnet.CredentialProvider/ConsentUI/Samples => Lithnet.CredentialProvider.UnitTests.x86/Samples/V1}/dump-consent-exe-x86.dat (100%) rename src/{Lithnet.CredentialProvider/ConsentUI/Samples => Lithnet.CredentialProvider.UnitTests.x86/Samples/V1}/dump-consent-msi-x86.dat (100%) rename src/{Lithnet.CredentialProvider/ConsentUI/Samples => Lithnet.CredentialProvider.UnitTests.x86/Samples/V1}/dump-consent-msix-x86.dat (100%) create mode 100644 src/Lithnet.CredentialProvider.UnitTests.x86/V1HeaderTests.cs delete mode 100644 src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-winsec-x86.dat rename src/Lithnet.CredentialProvider/Interop/Structs/{ConsentUIStructureHeader.cs => ConsentUIStructureHeaderBase.cs} (86%) create mode 100644 src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeaderV1.cs create mode 100644 src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeaderV2.cs delete mode 100644 src/Lithnet.CredentialProvider/NativeMethods.json 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..a3489d9 --- /dev/null +++ b/src/Lithnet.CredentialProvider.UnitTests.x64/Lithnet.CredentialProvider.UnitTests.x64.csproj @@ -0,0 +1,25 @@ + + + + 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 0000000000000000000000000000000000000000..ad14352e75ed533d472d18b8c56502ffa2aab3c4 GIT binary patch literal 408 zcmbQi$iM(Z49q|b0&+~eV44F$F|Yu6OhDYD1Qup+0xF(q!N`zq=53x|XzuH8;9OEx zYFv_1<*eVhCGH8hJ1!{ zhGHN;n4uC#moTI<xU|ftN*Wp?` zxBU@U;Qu=JaqhYI-&_M7in_KM#jOnI+ZnJfu>9Lj?l%kY5fm5)&9GWI>7GTki%!^& z;z}!BTzP)Z`oH)6yEXj$({4la**bT4=P+^j>hQ~9&W2^(66=(?Wx$vcH4gCb31sgw z=SY5u2kw=h>W+9~PeLo6vHh$Ds=xb*(M%U zE`@=51`t*BBRd|d=k5bq_W^3O&J0!zF$@6=MGW~2=|D1( zA(ugc!Hpr4A%`KAp%^F^4rJ#sqyXj1fqX}X0w4s5`vS$2!TO4Ua%l`D40=GZUnS literal 0 HcmV?d00001 diff --git a/src/Lithnet.CredentialProvider.UnitTests.x64/V1HeaderTests.cs b/src/Lithnet.CredentialProvider.UnitTests.x64/V1HeaderTests.cs new file mode 100644 index 0000000..6bf34d8 --- /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((ConsentUIElevationType)6, d.ElevationType); + 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((ConsentUIElevationType)5, d.ElevationType); + 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((ConsentUIElevationType)8, d.ElevationType); + 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((ConsentUIElevationType)4, d.ElevationType); + 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..fbd5af1 --- /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((ConsentUIElevationType)6, d.ElevationType); + 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((ConsentUIElevationType)5, d.ElevationType); + 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((ConsentUIElevationType)8, d.ElevationType); + 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((ConsentUIElevationType)4, d.ElevationType); + 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..d37d745 --- /dev/null +++ b/src/Lithnet.CredentialProvider.UnitTests.x86/Lithnet.CredentialProvider.UnitTests.x86.csproj @@ -0,0 +1,25 @@ + + + + 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..e4c6dbe --- /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((ConsentUIElevationType)6, d.ElevationType); + 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((ConsentUIElevationType)5, d.ElevationType); + 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((ConsentUIElevationType)8, d.ElevationType); + 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((ConsentUIElevationType)4, d.ElevationType); + 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..37596df 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 @@ -62,7 +66,8 @@ 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) { @@ -330,7 +335,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 311afd6fc1222df83e9605acdba8667c3dfa233a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 384 zcmZo*WMBXy24*1EU{zxHpuoVu0%S7*@ex%91}C88wx5Pf6F!~c@&StF0r4>))&h#_ zAO7Sj_I8R-%jD~NKdo4$!x=Jx@+l1Y4CM^P3`%V5l41XO{p(*r1%$dCh6lfmG~kPhVK0oi&$yK;b#fx&@BChIWh eG8i%#05LAN2b1J>4`A4Ue5wcZK?M*qFaQ8igGoUE 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 86% rename from src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeader.cs rename to src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeaderBase.cs index f016be1..f58c6b7 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 @@ -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..3d5ea3c 100644 --- a/src/Lithnet.CredentialProvider/Lithnet.CredentialProvider.csproj +++ b/src/Lithnet.CredentialProvider/Lithnet.CredentialProvider.csproj @@ -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