mirror of https://github.com/dahall/Vanara.git
Rearranged unit testing helper methods into Shared test project. Pulled all shared code into new project.
parent
f9f7068a9d
commit
e63b1b3a47
|
@ -0,0 +1,31 @@
|
|||
using System;
|
||||
using Vanara.InteropServices;
|
||||
using static Vanara.PInvoke.AdvApi32;
|
||||
using static Vanara.PInvoke.Kernel32;
|
||||
|
||||
namespace Vanara.PInvoke.Tests
|
||||
{
|
||||
public class PrivBlock : IDisposable
|
||||
{
|
||||
SafeCoTaskMemHandle prevState;
|
||||
SafeHTOKEN tok;
|
||||
|
||||
public PrivBlock(string priv, HPROCESS hProc = default, TokenAccess access = TokenAccess.TOKEN_ADJUST_PRIVILEGES | TokenAccess.TOKEN_QUERY)
|
||||
{
|
||||
if (hProc.IsNull) hProc = GetCurrentProcess();
|
||||
tok = SafeHTOKEN.FromProcess(hProc, access);
|
||||
var newPriv = new PTOKEN_PRIVILEGES(LUID.FromName(priv), PrivilegeAttributes.SE_PRIVILEGE_ENABLED);
|
||||
prevState = PTOKEN_PRIVILEGES.GetAllocatedAndEmptyInstance();
|
||||
if (!AdjustTokenPrivileges(tok, false, newPriv, (uint)prevState.Size, prevState, out var retLen))
|
||||
Win32Error.ThrowLastError();
|
||||
prevState.Size = (int)retLen;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
AdjustTokenPrivileges(tok, false, prevState);
|
||||
prevState.Dispose();
|
||||
tok.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -43,7 +43,11 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="CSharpRunner.cs" />
|
||||
<Compile Include="PrivBlock.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SuccessfulConstraint.cs" />
|
||||
<Compile Include="TempFile.cs" />
|
||||
<Compile Include="TestHelper.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ICSharpCode.Decompiler">
|
||||
|
@ -52,6 +56,33 @@
|
|||
<PackageReference Include="Microsoft.CodeAnalysis">
|
||||
<Version>3.1.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="NUnit">
|
||||
<Version>3.12.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="NUnit3TestAdapter">
|
||||
<Version>3.13.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="ObjectDumper">
|
||||
<Version>1.0.0.12</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Core\Vanara.Core.csproj">
|
||||
<Project>{241f73ee-9298-45c9-b869-a045dff94c03}</Project>
|
||||
<Name>Vanara.Core</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\PInvoke\Kernel32\Vanara.PInvoke.Kernel32.csproj">
|
||||
<Project>{842d436f-598c-47d7-b5aa-12399f8ccfe9}</Project>
|
||||
<Name>Vanara.PInvoke.Kernel32</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\PInvoke\Security\Vanara.PInvoke.Security.csproj">
|
||||
<Project>{392a14b0-1e10-4e88-9c13-0d965665ffb5}</Project>
|
||||
<Name>Vanara.PInvoke.Security</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\PInvoke\Shared\Vanara.PInvoke.Shared.csproj">
|
||||
<Project>{a5e519e9-feba-4fe3-93a5-b8269bef72f4}</Project>
|
||||
<Name>Vanara.PInvoke.Shared</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
|
@ -0,0 +1,29 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using static Vanara.PInvoke.Kernel32;
|
||||
|
||||
namespace Vanara.PInvoke.Tests
|
||||
{
|
||||
public class TempFile : IDisposable
|
||||
{
|
||||
public const string tmpstr = @"Temporary";
|
||||
|
||||
public TempFile(Kernel32.FileAccess dwDesiredAccess, FileShare dwShareMode, FileMode dwCreationDisposition = FileMode.OpenOrCreate, FileFlagsAndAttributes dwFlagsAndAttributes = FileFlagsAndAttributes.FILE_ATTRIBUTE_NORMAL) : this()
|
||||
{
|
||||
hFile = CreateFile(FullName, dwDesiredAccess, dwShareMode, null, dwCreationDisposition, dwFlagsAndAttributes, IntPtr.Zero);
|
||||
}
|
||||
|
||||
public TempFile(string contents = tmpstr)
|
||||
{
|
||||
FullName = Path.GetTempFileName(); File.WriteAllText(FullName, contents);
|
||||
}
|
||||
|
||||
public string FullName { get; }
|
||||
public SafeHFILE hFile { get; }
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
hFile?.Dispose(); File.Delete(FullName);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Vanara.InteropServices;
|
||||
|
||||
namespace Vanara.PInvoke.Tests
|
||||
{
|
||||
public static class TestHelper
|
||||
{
|
||||
public static void RunForEach<TEnum>(Type lib, string name, Func<TEnum, object[]> makeParam, Action<TEnum, object, object[]> action = null, Action<Exception> error = null) where TEnum : Enum
|
||||
{
|
||||
var mi = lib.GetMethods(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static).Where(m => m.IsGenericMethod && m.Name == name).First();
|
||||
if (mi is null) throw new ArgumentException("Unable to find method.");
|
||||
foreach (var e in Enum.GetValues(typeof(TEnum)).Cast<TEnum>())
|
||||
{
|
||||
var type = CorrespondingTypeAttribute.GetCorrespondingTypes(e).FirstOrDefault();
|
||||
if (type is null)
|
||||
{
|
||||
TestContext.WriteLine($"No corresponding type found for {e}.");
|
||||
continue;
|
||||
}
|
||||
var gmi = mi.MakeGenericMethod(type);
|
||||
var param = makeParam(e);
|
||||
try
|
||||
{
|
||||
var ret = gmi.Invoke(null, param);
|
||||
action?.Invoke(e, ret, param);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
error?.Invoke(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void WriteValues(this object value)
|
||||
{
|
||||
TestContext.WriteLine(ObjectDumper.ObjectDumperExtensions.DumpToString(value, value.ToString()));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -454,27 +454,4 @@ namespace Vanara.PInvoke.Tests
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class TempFile : IDisposable
|
||||
{
|
||||
public const string tmpstr = @"Temporary";
|
||||
|
||||
public TempFile(Kernel32.FileAccess dwDesiredAccess, FileShare dwShareMode, FileMode dwCreationDisposition = FileMode.OpenOrCreate, FileFlagsAndAttributes dwFlagsAndAttributes = FileFlagsAndAttributes.FILE_ATTRIBUTE_NORMAL) : this()
|
||||
{
|
||||
hFile = CreateFile(FullName, dwDesiredAccess, dwShareMode, null, dwCreationDisposition, dwFlagsAndAttributes, IntPtr.Zero);
|
||||
}
|
||||
|
||||
public TempFile(string contents = tmpstr)
|
||||
{
|
||||
FullName = Path.GetTempFileName(); File.WriteAllText(FullName, contents);
|
||||
}
|
||||
|
||||
public string FullName { get; }
|
||||
public SafeHFILE hFile { get; }
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
hFile?.Dispose(); File.Delete(FullName);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -65,7 +65,6 @@
|
|||
<Compile Include="Kernel32Tests.cs" />
|
||||
<Compile Include="ConsoleTests.cs" />
|
||||
<Compile Include="DebugApiTests.cs" />
|
||||
<Compile Include="SuccessfulConstraint.cs" />
|
||||
<Compile Include="TLHelp32Tests.cs" />
|
||||
<Compile Include="SysInfoTests.cs" />
|
||||
</ItemGroup>
|
||||
|
@ -86,9 +85,9 @@
|
|||
<Project>{a5e519e9-feba-4fe3-93a5-b8269bef72f4}</Project>
|
||||
<Name>Vanara.PInvoke.Shared</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\CSharpRunner\CSharpRunner.csproj">
|
||||
<ProjectReference Include="..\..\CSharpRunner\Shared.csproj">
|
||||
<Project>{a96cff10-0967-429a-8700-4a86c97c5603}</Project>
|
||||
<Name>CSharpRunner</Name>
|
||||
<Name>Shared</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -98,9 +97,6 @@
|
|||
<PackageReference Include="NUnit3TestAdapter">
|
||||
<Version>3.13.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="ObjectDumper">
|
||||
<Version>1.0.0.12</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
|
|
|
@ -3,7 +3,6 @@ using System;
|
|||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Vanara.InteropServices;
|
||||
using static Vanara.PInvoke.AdvApi32;
|
||||
using static Vanara.PInvoke.Kernel32;
|
||||
|
||||
namespace Vanara.PInvoke.Tests
|
||||
|
@ -117,28 +116,4 @@ namespace Vanara.PInvoke.Tests
|
|||
TestContext.WriteLine($"{min} : {max} : {flg}");
|
||||
}
|
||||
}
|
||||
|
||||
internal class PrivBlock : IDisposable
|
||||
{
|
||||
SafeCoTaskMemHandle prevState;
|
||||
SafeHTOKEN tok;
|
||||
|
||||
public PrivBlock(string priv, HPROCESS hProc = default, TokenAccess access = TokenAccess.TOKEN_ADJUST_PRIVILEGES | TokenAccess.TOKEN_QUERY)
|
||||
{
|
||||
if (hProc.IsNull) hProc = GetCurrentProcess();
|
||||
tok = SafeHTOKEN.FromProcess(hProc, access);
|
||||
var newPriv = new PTOKEN_PRIVILEGES(LUID.FromName(priv), PrivilegeAttributes.SE_PRIVILEGE_ENABLED);
|
||||
prevState = PTOKEN_PRIVILEGES.GetAllocatedAndEmptyInstance();
|
||||
if (!AdjustTokenPrivileges(tok, false, newPriv, (uint)prevState.Size, prevState, out var retLen))
|
||||
Win32Error.ThrowLastError();
|
||||
prevState.Size = (int)retLen;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
AdjustTokenPrivileges(tok, false, prevState);
|
||||
prevState.Dispose();
|
||||
tok.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,7 +15,7 @@ namespace Vanara.PInvoke.Tests
|
|||
public void CreatePipeTest()
|
||||
{
|
||||
var saAttr = new SECURITY_ATTRIBUTES { bInheritHandle = true };
|
||||
Tester.Test(() => CreatePipe(out var g_hChildStd_OUT_Rd, out var g_hChildStd_OUT_Wr, saAttr, 0));
|
||||
Assert.That(CreatePipe(out var g_hChildStd_OUT_Rd, out var g_hChildStd_OUT_Wr, saAttr, 0), ResultIs.Successful);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -24,36 +24,4 @@ namespace Vanara.PInvoke.Tests
|
|||
//Assert.That(CreateNamedPipe(), Is.Zero);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Tester
|
||||
{
|
||||
public static void Test<TRet>(Func<TRet> f, TRet? expected = default) where TRet : struct
|
||||
{
|
||||
TRet ret = f();
|
||||
switch (ret)
|
||||
{
|
||||
case bool b:
|
||||
if (!b)
|
||||
TestContext.WriteLine(Win32Error.GetLastError());
|
||||
Assert.That(b, Is.EqualTo(true));
|
||||
break;
|
||||
case Win32Error we:
|
||||
if (we.Failed)
|
||||
TestContext.WriteLine(we);
|
||||
Assert.That(we, Is.EqualTo((Win32Error)0));
|
||||
break;
|
||||
case HRESULT hr:
|
||||
if (hr.Failed)
|
||||
TestContext.WriteLine(hr);
|
||||
Assert.That(hr, Is.EqualTo((HRESULT)0));
|
||||
break;
|
||||
default:
|
||||
if (expected.HasValue)
|
||||
Assert.That(ret, Is.EqualTo(expected.Value));
|
||||
else
|
||||
Assert.Fail();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,40 +9,6 @@ using static Vanara.PInvoke.Kernel32;
|
|||
|
||||
namespace Vanara.PInvoke.Tests
|
||||
{
|
||||
public static class TestHelper
|
||||
{
|
||||
public static void RunForEach<TEnum>(Type lib, string name, Func<TEnum, object[]> makeParam, Action<TEnum, object, object[]> action = null, Action<Exception> error = null) where TEnum : Enum
|
||||
{
|
||||
var mi = lib.GetMethods(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static).Where(m => m.IsGenericMethod && m.Name == name).First();
|
||||
if (mi is null) throw new ArgumentException("Unable to find method.");
|
||||
foreach (var e in Enum.GetValues(typeof(TEnum)).Cast<TEnum>())
|
||||
{
|
||||
var type = CorrespondingTypeAttribute.GetCorrespondingTypes(e).FirstOrDefault();
|
||||
if (type is null)
|
||||
{
|
||||
TestContext.WriteLine($"No corresponding type found for {e}.");
|
||||
continue;
|
||||
}
|
||||
var gmi = mi.MakeGenericMethod(type);
|
||||
var param = makeParam(e);
|
||||
try
|
||||
{
|
||||
var ret = gmi.Invoke(null, param);
|
||||
action?.Invoke(e, ret, param);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
error?.Invoke(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void WriteValues(this object value)
|
||||
{
|
||||
TestContext.WriteLine(ObjectDumper.ObjectDumperExtensions.DumpToString(value, value.ToString()));
|
||||
}
|
||||
}
|
||||
|
||||
[TestFixture]
|
||||
public class ProcessThreadsTests
|
||||
{
|
||||
|
|
|
@ -220,12 +220,10 @@ namespace Vanara.PInvoke.Tests
|
|||
Assert.That(daclPresent, Is.True);
|
||||
Assert.That(pAcl, Is.Not.EqualTo(IntPtr.Zero));
|
||||
var hardAcl = ((IntPtr)pAcl).ToStructure<ACL>();
|
||||
var ari = new ACL_REVISION_INFORMATION();
|
||||
b = GetAclInformation(pAcl, ref ari, (uint)Marshal.SizeOf(typeof(ACL_REVISION_INFORMATION)), ACL_INFORMATION_CLASS.AclRevisionInformation);
|
||||
b = GetAclInformation(pAcl, out ACL_REVISION_INFORMATION ari, (uint)Marshal.SizeOf(typeof(ACL_REVISION_INFORMATION)), ACL_INFORMATION_CLASS.AclRevisionInformation);
|
||||
Assert.That(b, Is.True);
|
||||
Assert.That(ari.AclRevision, Is.EqualTo(hardAcl.AclRevision));
|
||||
var asi = new ACL_SIZE_INFORMATION();
|
||||
b = GetAclInformation(pAcl, ref asi, (uint)Marshal.SizeOf(typeof(ACL_SIZE_INFORMATION)), ACL_INFORMATION_CLASS.AclSizeInformation);
|
||||
b = GetAclInformation(pAcl, out ACL_SIZE_INFORMATION asi, (uint)Marshal.SizeOf(typeof(ACL_SIZE_INFORMATION)), ACL_INFORMATION_CLASS.AclSizeInformation);
|
||||
Assert.That(b, Is.True);
|
||||
Assert.That(asi.AceCount, Is.EqualTo(hardAcl.AceCount));
|
||||
for (var i = 0U; i < asi.AceCount; i++)
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.AccessControl;
|
||||
using System.Text;
|
||||
using Vanara.InteropServices;
|
||||
using static Vanara.PInvoke.AdvApi32;
|
||||
using static Vanara.PInvoke.Kernel32;
|
||||
|
||||
namespace Vanara.PInvoke.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class SecurityBaseApiTests
|
||||
{
|
||||
[Test]
|
||||
public void AddResourceAttributeAceTest()
|
||||
{
|
||||
using (var pNewSacl = new SafePACL(256))
|
||||
{
|
||||
using (var capId = new SafePSID("S-1-17-22"))
|
||||
Assert.That(AddScopedPolicyIDAce(pNewSacl, ACL_REVISION, 0, 0, capId), ResultIs.Successful);
|
||||
|
||||
var attrValues = new[] { 12L, 32L };
|
||||
using (var pattrValues = SafeHGlobalHandle.CreateFromList(attrValues))
|
||||
{
|
||||
var csattr = new CLAIM_SECURITY_ATTRIBUTE_V1
|
||||
{
|
||||
Name = "Int",
|
||||
ValueType = CLAIM_SECURITY_ATTRIBUTE_TYPE.CLAIM_SECURITY_ATTRIBUTE_TYPE_INT64,
|
||||
ValueCount = (uint)attrValues.Length,
|
||||
Values = new CLAIM_SECURITY_ATTRIBUTE_V1.VALUESUNION { pInt64 = (IntPtr)pattrValues }
|
||||
};
|
||||
var attr = new[] { csattr };
|
||||
using (var pattr = SafeHGlobalHandle.CreateFromList(attr))
|
||||
{
|
||||
var csi = CLAIM_SECURITY_ATTRIBUTES_INFORMATION.Default;
|
||||
csi.AttributeCount = (uint)attr.Length;
|
||||
csi.Attribute.pAttributeV1 = (IntPtr)pattr;
|
||||
var len = 0U;
|
||||
Assert.That(AddResourceAttributeAce(pNewSacl, ACL_REVISION, 0, 0, SafePSID.Everyone, csi, ref len), ResultIs.Successful);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CheckTokenCapabilityTest()
|
||||
{
|
||||
using (var hTok = SafeHTOKEN.CurrentProcessToken)
|
||||
Assert.That(CheckTokenCapability(hTok, SafePSID.Current, out var has), ResultIs.Successful);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeriveCapabilitySidsFromNameTest()
|
||||
{
|
||||
Assert.That(DeriveCapabilitySidsFromName("microsoft.hsaTestCustomCapability_q536wpkpf5cy2", out var grpsids, out var grpcnt, out var sids, out var cnt), ResultIs.Successful);
|
||||
grpsids.Length = grpcnt; sids.Length = cnt;
|
||||
Assert.That(grpsids.Length, Is.EqualTo(grpcnt));
|
||||
Assert.That(grpsids, Is.Not.Empty);
|
||||
Assert.That(sids, Is.Not.Empty);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,9 +9,10 @@
|
|||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Vanara.PInvoke.Tests</RootNamespace>
|
||||
<AssemblyName>UnitTest.PInvoke.Security</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -41,6 +42,7 @@
|
|||
<Compile Include="AdvApi32\AdvApi32Tests.cs" />
|
||||
<Compile Include="AdvApi32\AuditTests.cs" />
|
||||
<Compile Include="AdvApi32\AppMgmtTests.cs" />
|
||||
<Compile Include="AdvApi32\SecurityBaseApiTests.cs" />
|
||||
<Compile Include="AdvApi32\ServiceTests.cs" />
|
||||
<Compile Include="AdvApi32\PSIDTests.cs" />
|
||||
<Compile Include="Authz\AuthzTests.cs" />
|
||||
|
@ -70,6 +72,10 @@
|
|||
<Project>{a5e519e9-feba-4fe3-93a5-b8269bef72f4}</Project>
|
||||
<Name>Vanara.PInvoke.Shared</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\CSharpRunner\Shared.csproj">
|
||||
<Project>{a96cff10-0967-429a-8700-4a86c97c5603}</Project>
|
||||
<Name>Shared</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<ItemGroup>
|
||||
|
|
|
@ -161,7 +161,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.SearchApi",
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.WinTrust", "PInvoke\WinTrust\Vanara.PInvoke.WinTrust.csproj", "{3EDE955E-50DE-4E1D-97E8-31E4E6A83E7D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpRunner", "UnitTests\CSharpRunner\CSharpRunner.csproj", "{A96CFF10-0967-429A-8700-4A86C97C5603}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shared", "UnitTests\CSharpRunner\Shared.csproj", "{A96CFF10-0967-429A-8700-4A86C97C5603}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
|
Loading…
Reference in New Issue