<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Windows_NT-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Windows_NT-Release|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Unix-Debug|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Unix-Release|AnyCPU'" />
<ItemGroup>
<Compile Include="System\Runtime\CompilerServices\IUnknownConstantAttributeTests.cs" />
<Compile Include="System\Runtime\InteropServices\AllowReversePInvokeCallsAttributeTests.cs" />
<Compile Include="System\Runtime\InteropServices\MarshalAsAttributeTests.cs" />
<Compile Include="System\Runtime\InteropServices\MarshalTests.cs" />
<Compile Include="System\Runtime\InteropServices\MarshalTests.Windows.cs" Condition="'$(TargetsWindows)' == 'true'" />
+ <Compile Include="System\Runtime\InteropServices\Marshal\Copy\ByteArrayTests.cs" />
+ <Compile Include="System\Runtime\InteropServices\Marshal\Copy\CharArrayTests.cs" />
+ <Compile Include="System\Runtime\InteropServices\Marshal\Copy\DoubleArrayTests.cs" />
+ <Compile Include="System\Runtime\InteropServices\Marshal\Copy\Int16ArrayTests.cs" />
+ <Compile Include="System\Runtime\InteropServices\Marshal\Copy\Int32ArrayTests.cs" />
+ <Compile Include="System\Runtime\InteropServices\Marshal\Copy\Int64ArrayTests.cs" />
+ <Compile Include="System\Runtime\InteropServices\Marshal\Copy\IntPtrArrayTests.cs" />
+ <Compile Include="System\Runtime\InteropServices\Marshal\Copy\SingleArrayTests.cs" />
+ <Compile Include="System\Runtime\InteropServices\Marshal\DestroyStructureTests.cs" />
+ <Compile Include="System\Runtime\InteropServices\Marshal\PtrToStructureTests.cs" />
+ <Compile Include="System\Runtime\InteropServices\Marshal\PtrToStringTests.cs" />
+ <Compile Include="System\Runtime\InteropServices\Marshal\SizeOfTests.cs" />
+ <Compile Include="System\Runtime\InteropServices\Marshal\GetExceptionForHRTests.cs" />
+ <Compile Include="System\Runtime\InteropServices\Marshal\GetNativeVariantForObjectTests.cs" />
+ <Compile Include="System\Runtime\InteropServices\Marshal\GetObjectForNativeVariantTests.cs" />
+ <Compile Include="System\Runtime\InteropServices\Marshal\GetObjectsForNativeVariantsTests.cs" />
+ <Compile Include="System\Runtime\InteropServices\Marshal\OffsetOfTests.cs" />
+ <Compile Include="System\Runtime\InteropServices\Marshal\ReadWrite\ByteTests.cs" />
+ <Compile Include="System\Runtime\InteropServices\Marshal\ReadWrite\Int16Tests.cs" />
+ <Compile Include="System\Runtime\InteropServices\Marshal\ReadWrite\Int32Tests.cs" />
+ <Compile Include="System\Runtime\InteropServices\Marshal\ReadWrite\Int64Tests.cs" />
+ <Compile Include="System\Runtime\InteropServices\Marshal\ReadWrite\IntPtrTests.cs" />
+ <Compile Include="System\Runtime\InteropServices\Marshal\ReadWrite\ObjectTests.cs" />
+ <Compile Include="System\Runtime\InteropServices\Marshal\StringMarshalingTests.cs" />
+ <Compile Include="System\Runtime\InteropServices\Marshal\StructureToPtrTests.cs" />
+ <Compile Include="System\Runtime\InteropServices\Marshal\UnsafeAddrOfPinnedArrayElementTests.cs" />
<Compile Condition="'$(TargetGroup)' != 'uap'" Include="System\Runtime\InteropServices\PrimaryInteropAssemblyAttributeTests.cs" />
<Compile Include="System\Runtime\InteropServices\ProgIdAttributeTests.cs" />
<Compile Include="System\Runtime\InteropServices\RuntimeEnvironmentTests.cs" />
<Compile Include="System\Runtime\InteropServices\TypeLibVersionAttributeTests.cs" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
+</Project>
\ No newline at end of file
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+ public class ByteArrayTests
+ {
+ public static readonly object[][] ArrayData =
+ {
+ new object[] { new byte[]{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } }
+ };
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void NullValueArguments_ThrowsArgumentNullException(byte[] TestArray)
+ {
+ byte[] array = null;
+ AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(TestArray, 0, IntPtr.Zero, 0));
+ AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(array, 0, new IntPtr(1), 0));
+ AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(new IntPtr(1), array, 0, 0));
+ AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(IntPtr.Zero, TestArray, 0, 0));
+ }
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void OutOfRangeArguments_ThrowsArgumentOutOfRangeException(byte[] TestArray)
+ {
+ int sizeOfArray = sizeof(byte) * TestArray.Length;
+ IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+ try
+ {
+ Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 0, ptr, TestArray.Length + 1));
+ Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, TestArray.Length + 1, ptr, 1));
+ Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 2, ptr, TestArray.Length));
+ }
+ finally
+ {
+ Marshal.FreeCoTaskMem(ptr);
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void CopyRoundTrip_MatchesOriginalArray(byte[] TestArray)
+ {
+ int sizeOfArray = sizeof(byte) * TestArray.Length;
+ IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+ try
+ {
+ Marshal.Copy(TestArray, 0, ptr, TestArray.Length);
+
+ byte[] array1 = new byte[TestArray.Length];
+ Marshal.Copy(ptr, array1, 0, TestArray.Length);
+ Assert.Equal<byte>(TestArray, array1);
+
+ Marshal.Copy(TestArray, 2, ptr, TestArray.Length - 4);
+ byte[] array2 = new byte[TestArray.Length];
+ Marshal.Copy(ptr, array2, 2, TestArray.Length - 4);
+ Assert.Equal<byte>(TestArray.AsSpan(2, TestArray.Length - 4).ToArray(), array2.AsSpan(2, TestArray.Length - 4).ToArray());
+ }
+ finally
+ {
+ Marshal.FreeCoTaskMem(ptr);
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+ public class CharArrayTests
+ {
+ public static readonly object[][] ArrayData =
+ {
+ new object[] { new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' } }
+ };
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void NullValueArguments_ThrowsArgumentNullException(char[] TestArray)
+ {
+ char[] array = null;
+ AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(TestArray, 0, IntPtr.Zero, 0));
+ AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(array, 0, new IntPtr(1), 0));
+ AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(new IntPtr(1), array, 0, 0));
+ AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(IntPtr.Zero, TestArray, 0, 0));
+ }
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void OutOfRangeArguments_ThrowsArgumentOutOfRangeException(char[] TestArray)
+ {
+ int sizeOfArray = sizeof(char) * TestArray.Length;
+ IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+ try
+ {
+ Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 0, ptr, TestArray.Length + 1));
+ Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, TestArray.Length + 1, ptr, 1));
+ Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 2, ptr, TestArray.Length));
+ }
+ finally
+ {
+ Marshal.FreeCoTaskMem(ptr);
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void CopyRoundTrip_MatchesOriginalArray(char[] TestArray)
+ {
+ int sizeOfArray = sizeof(char) * TestArray.Length;
+ IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+ try
+ {
+ Marshal.Copy(TestArray, 0, ptr, TestArray.Length);
+
+ char[] array1 = new char[TestArray.Length];
+ Marshal.Copy(ptr, array1, 0, TestArray.Length);
+ Assert.Equal<char>(TestArray, array1);
+
+ Marshal.Copy(TestArray, 2, ptr, TestArray.Length - 4);
+ char[] array2 = new char[TestArray.Length];
+ Marshal.Copy(ptr, array2, 2, TestArray.Length - 4);
+ Assert.Equal<char>(TestArray.AsSpan(2, TestArray.Length - 4).ToArray(), array2.AsSpan(2, TestArray.Length - 4).ToArray());
+ }
+ finally
+ {
+ Marshal.FreeCoTaskMem(ptr);
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+ public class DoubleArrayTests
+ {
+ public static readonly object[][] ArrayData =
+ {
+ new object[] { new double[] { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 } }
+ };
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void NullValueArguments_ThrowsArgumentNullException(double[] TestArray)
+ {
+ double[] array = null;
+ AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(TestArray, 0, IntPtr.Zero, 0));
+ AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(array, 0, new IntPtr(1), 0));
+ AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(new IntPtr(1), array, 0, 0));
+ AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(IntPtr.Zero, TestArray, 0, 0));
+ }
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void OutOfRangeArguments_ThrowsArgumentOutOfRangeException(double[] TestArray)
+ {
+ int sizeOfArray = sizeof(double) * TestArray.Length;
+ IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+ try
+ {
+ Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 0, ptr, TestArray.Length + 1));
+ Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, TestArray.Length + 1, ptr, 1));
+ Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 2, ptr, TestArray.Length));
+ }
+ finally
+ {
+ Marshal.FreeCoTaskMem(ptr);
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void CopyRoundTrip_MatchesOriginalArray(double[] TestArray)
+ {
+ int sizeOfArray = sizeof(double) * TestArray.Length;
+ IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+ try
+ {
+ Marshal.Copy(TestArray, 0, ptr, TestArray.Length);
+
+ double[] array1 = new double[TestArray.Length];
+ Marshal.Copy(ptr, array1, 0, TestArray.Length);
+ Assert.Equal<double>(TestArray, array1);
+
+ Marshal.Copy(TestArray, 2, ptr, TestArray.Length - 4);
+ double[] array2 = new double[TestArray.Length];
+ Marshal.Copy(ptr, array2, 2, TestArray.Length - 4);
+ Assert.Equal<double>(TestArray.AsSpan(2, TestArray.Length - 4).ToArray(), array2.AsSpan(2, TestArray.Length - 4).ToArray());
+ }
+ finally
+ {
+ Marshal.FreeCoTaskMem(ptr);
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+ public class Int16ArrayTests
+ {
+ public static readonly object[][] ArrayData =
+ {
+ new object[] { new short[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } }
+ };
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void NullValueArguments_ThrowsArgumentNullException(short[] TestArray)
+ {
+ short[] array = null;
+ AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(TestArray, 0, IntPtr.Zero, 0));
+ AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(array, 0, new IntPtr(1), 0));
+ AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(new IntPtr(1), array, 0, 0));
+ AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(IntPtr.Zero, TestArray, 0, 0));
+ }
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void OutOfRangeArguments_ThrowsArgumentOutOfRangeException(short[] TestArray)
+ {
+ int sizeOfArray = sizeof(short) * TestArray.Length;
+ IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+ try
+ {
+ Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 0, ptr, TestArray.Length + 1));
+ Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, TestArray.Length + 1, ptr, 1));
+ Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 2, ptr, TestArray.Length));
+ }
+ finally
+ {
+ Marshal.FreeCoTaskMem(ptr);
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void CopyRoundTrip_MatchesOriginalArray(short[] TestArray)
+ {
+ int sizeOfArray = sizeof(short) * TestArray.Length;
+ IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+ try
+ {
+ Marshal.Copy(TestArray, 0, ptr, TestArray.Length);
+
+ short[] array1 = new short[TestArray.Length];
+ Marshal.Copy(ptr, array1, 0, TestArray.Length);
+ Assert.Equal<short>(TestArray, array1);
+
+ Marshal.Copy(TestArray, 2, ptr, TestArray.Length - 4);
+ short[] array2 = new short[TestArray.Length];
+ Marshal.Copy(ptr, array2, 2, TestArray.Length - 4);
+ Assert.Equal<short>(TestArray.AsSpan(2, TestArray.Length - 4).ToArray(), array2.AsSpan(2, TestArray.Length - 4).ToArray());
+ }
+ finally
+ {
+ Marshal.FreeCoTaskMem(ptr);
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+ public class Int32ArrayTests
+ {
+ public static readonly object[][] ArrayData =
+ {
+ new object[] { new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } }
+ };
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void NullValueArguments_ThrowsArgumentNullException(int[] TestArray)
+ {
+ int[] array = null;
+ AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(TestArray, 0, IntPtr.Zero, 0));
+ AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(array, 0, new IntPtr(1), 0));
+ AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(new IntPtr(1), array, 0, 0));
+ AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(IntPtr.Zero, TestArray, 0, 0));
+ }
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void OutOfRangeArguments_ThrowsArgumentOutOfRangeException(int[] TestArray)
+ {
+ int sizeOfArray = sizeof(int) * TestArray.Length;
+ IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+ try
+ {
+ Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 0, ptr, TestArray.Length + 1));
+ Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, TestArray.Length + 1, ptr, 1));
+ Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 2, ptr, TestArray.Length));
+ }
+ finally
+ {
+ Marshal.FreeCoTaskMem(ptr);
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void CopyRoundTrip_MatchesOriginalArray(int[] TestArray)
+ {
+ int sizeOfArray = sizeof(int) * TestArray.Length;
+ IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+ try
+ {
+ Marshal.Copy(TestArray, 0, ptr, TestArray.Length);
+
+ int[] array1 = new int[TestArray.Length];
+ Marshal.Copy(ptr, array1, 0, TestArray.Length);
+ Assert.Equal<int>(TestArray, array1);
+
+ Marshal.Copy(TestArray, 2, ptr, TestArray.Length - 4);
+ int[] array2 = new int[TestArray.Length];
+ Marshal.Copy(ptr, array2, 2, TestArray.Length - 4);
+ Assert.Equal<int>(TestArray.AsSpan(2, TestArray.Length - 4).ToArray(), array2.AsSpan(2, TestArray.Length - 4).ToArray());
+ }
+ finally
+ {
+ Marshal.FreeCoTaskMem(ptr);
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+ public class Int64ArrayTests
+ {
+ public static readonly object[][] ArrayData =
+ {
+ new object[] { new long[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } }
+ };
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void NullValueArguments_ThrowsArgumentNullException(long[] TestArray)
+ {
+ long[] array = null;
+ AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(TestArray, 0, IntPtr.Zero, 0));
+ AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(array, 0, new IntPtr(1), 0));
+ AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(new IntPtr(1), array, 0, 0));
+ AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(IntPtr.Zero, TestArray, 0, 0));
+ }
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void OutOfRangeArguments_ThrowsArgumentOutOfRangeException(long[] TestArray)
+ {
+ int sizeOfArray = sizeof(long) * TestArray.Length;
+ IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+ try
+ {
+ Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 0, ptr, TestArray.Length + 1));
+ Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, TestArray.Length + 1, ptr, 1));
+ Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 2, ptr, TestArray.Length));
+ }
+ finally
+ {
+ Marshal.FreeCoTaskMem(ptr);
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void CopyRoundTrip_MatchesOriginalArray(long[] TestArray)
+ {
+ int sizeOfArray = sizeof(long) * TestArray.Length;
+ IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+ try
+ {
+ Marshal.Copy(TestArray, 0, ptr, TestArray.Length);
+
+ long[] array1 = new long[TestArray.Length];
+ Marshal.Copy(ptr, array1, 0, TestArray.Length);
+ Assert.Equal<long>(TestArray, array1);
+
+ Marshal.Copy(TestArray, 2, ptr, TestArray.Length - 4);
+ long[] array2 = new long[TestArray.Length];
+ Marshal.Copy(ptr, array2, 2, TestArray.Length - 4);
+ Assert.Equal<long>(TestArray.AsSpan(2, TestArray.Length - 4).ToArray(), array2.AsSpan(2, TestArray.Length - 4).ToArray());
+ }
+ finally
+ {
+ Marshal.FreeCoTaskMem(ptr);
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Linq;
+using Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+ public class IntPtrArrayTests
+ {
+ public static readonly object[][] ArrayData =
+ {
+ new object[] { Enumerable.Range(0, 10).Select(i => new IntPtr(i)).ToArray() }
+ };
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void NullValueArguments_ThrowsArgumentNullException(IntPtr[] TestArray)
+ {
+ IntPtr[] array = null;
+ AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(TestArray, 0, IntPtr.Zero, 0));
+ AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(array, 0, new IntPtr(1), 0));
+ AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(new IntPtr(1), array, 0, 0));
+ AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(IntPtr.Zero, TestArray, 0, 0));
+ }
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void OutOfRangeArguments_ThrowsArgumentOutOfRangeException(IntPtr[] TestArray)
+ {
+ int sizeOfArray = IntPtr.Size * TestArray.Length;
+ IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+ try
+ {
+ Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 0, ptr, TestArray.Length + 1));
+ Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, TestArray.Length + 1, ptr, 1));
+ Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 2, ptr, TestArray.Length));
+ }
+ finally
+ {
+ Marshal.FreeCoTaskMem(ptr);
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void CopyRoundTrip_MatchesOriginalArray(IntPtr[] TestArray)
+ {
+ int sizeOfArray = IntPtr.Size * TestArray.Length;
+ IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+ try
+ {
+ Marshal.Copy(TestArray, 0, ptr, TestArray.Length);
+
+ IntPtr[] array1 = new IntPtr[TestArray.Length];
+ Marshal.Copy(ptr, array1, 0, TestArray.Length);
+ Assert.Equal<IntPtr>(TestArray, array1);
+
+ Marshal.Copy(TestArray, 2, ptr, TestArray.Length - 4);
+ IntPtr[] array2 = new IntPtr[TestArray.Length];
+ Marshal.Copy(ptr, array2, 2, TestArray.Length - 4);
+ Assert.Equal<IntPtr>(TestArray.AsSpan(2, TestArray.Length - 4).ToArray(), array2.AsSpan(2, TestArray.Length - 4).ToArray());
+ }
+ finally
+ {
+ Marshal.FreeCoTaskMem(ptr);
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+ public class SingleArrayTests
+ {
+ public static readonly object[][] ArrayData =
+ {
+ new object[] { new float[] { 0.0F, 1.0F, 2.0F, 3.0F, 4.0F, 5.0F, 6.0F, 7.0F, 8.0F, 9.0F } }
+ };
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void NullValueArguments_ThrowsArgumentNullException(float[] TestArray)
+ {
+ float[] array = null;
+ AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(TestArray, 0, IntPtr.Zero, 0));
+ AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(array, 0, new IntPtr(1), 0));
+ AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(new IntPtr(1), array, 0, 0));
+ AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(IntPtr.Zero, TestArray, 0, 0));
+ }
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void OutOfRangeArguments_ThrowsArgumentOutOfRangeException(float[] TestArray)
+ {
+ int sizeOfArray = sizeof(float) * TestArray.Length;
+ IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+ try
+ {
+ Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 0, ptr, TestArray.Length + 1));
+ Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, TestArray.Length + 1, ptr, 1));
+ Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 2, ptr, TestArray.Length));
+ }
+ finally
+ {
+ Marshal.FreeCoTaskMem(ptr);
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void CopyRoundTrip_MatchesOriginalArray(float[] TestArray)
+ {
+ int sizeOfArray = sizeof(float) * TestArray.Length;
+ IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+ try
+ {
+ Marshal.Copy(TestArray, 0, ptr, TestArray.Length);
+
+ float[] array1 = new float[TestArray.Length];
+ Marshal.Copy(ptr, array1, 0, TestArray.Length);
+ Assert.Equal<float>(TestArray, array1);
+
+ Marshal.Copy(TestArray, 2, ptr, TestArray.Length - 4);
+ float[] array2 = new float[TestArray.Length];
+ Marshal.Copy(ptr, array2, 2, TestArray.Length - 4);
+ Assert.Equal<float>(TestArray.AsSpan(2, TestArray.Length - 4).ToArray(), array2.AsSpan(2, TestArray.Length - 4).ToArray());
+ }
+ finally
+ {
+ Marshal.FreeCoTaskMem(ptr);
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+ public class DestroyStructureTests
+ {
+ [StructLayout(LayoutKind.Sequential)]
+ public struct SomeTestStruct
+ {
+ public int i;
+ public String s;
+ }
+
+ [StructLayout(LayoutKind.Auto)]
+ public struct SomeTestStruct_Auto
+ {
+ public int i;
+ }
+
+ [Fact]
+ public void DestroyStructure_Negative()
+ {
+ IntPtr ip;
+
+ ip = IntPtr.Zero;
+ AssertExtensions.Throws<ArgumentNullException>("ptr", () => Marshal.DestroyStructure<SomeTestStruct>(ip));
+
+ ip = new IntPtr(123);
+ AssertExtensions.Throws<ArgumentNullException>("structureType", () => Marshal.DestroyStructure(ip, null));
+
+ SomeTestStruct_Auto someTs_Auto = new SomeTestStruct_Auto();
+ Assert.Throws<ArgumentException>(() => Marshal.DestroyStructure(ip, someTs_Auto.GetType()));
+ }
+
+ [Fact]
+ public void DestroyStructure_Positive()
+ {
+ SomeTestStruct someTestStruct = new SomeTestStruct();
+ IntPtr ip = Marshal.AllocHGlobal(Marshal.SizeOf(someTestStruct));
+ try
+ {
+ someTestStruct.s = null;
+ //Generic
+ Marshal.StructureToPtr(someTestStruct, ip, false);
+ Marshal.DestroyStructure<SomeTestStruct>(ip);
+ //None-Generic
+ Marshal.StructureToPtr(someTestStruct, ip, false);
+ Marshal.DestroyStructure(ip, typeof(SomeTestStruct));
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(ip);
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+ public class GetExceptionForHRTests
+ {
+ [Theory]
+ [InlineData(unchecked((int)0x80020006))]
+ [InlineData(unchecked((int)0x80020101))]
+ [ActiveIssue(30866)]
+ public void GetExceptionForHR_EqualsErrorCode(int err)
+ {
+ Exception ex = Marshal.GetExceptionForHR(err);
+ Assert.Equal(err, ex.HResult);
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+ public class GetNativeVariantForObjectTests
+ {
+ internal struct Variant
+ {
+#pragma warning disable 0649
+ public ushort vt;
+ public ushort wReserved1;
+ public ushort wReserved2;
+ public ushort wReserved3;
+ public IntPtr bstrVal;
+ public IntPtr pRecInfo;
+#pragma warning restore 0649
+ }
+
+#pragma warning disable 618
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public static void NullParameter()
+ {
+ AssertExtensions.Throws<ArgumentNullException>("pDstNativeVariant", () => Marshal.GetNativeVariantForObject(new object(), IntPtr.Zero));
+ AssertExtensions.Throws<ArgumentNullException>("pDstNativeVariant", () => Marshal.GetNativeVariantForObject<int>(1, IntPtr.Zero));
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public static void EmptyObject()
+ {
+ Variant v = new Variant();
+ IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
+ try
+ {
+ Marshal.GetNativeVariantForObject(null, pNative);
+ object o = Marshal.GetObjectForNativeVariant(pNative);
+ Assert.Null(o);
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(pNative);
+ }
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public static void PrimitiveType()
+ {
+ Variant v = new Variant();
+ IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
+ try
+ {
+ Marshal.GetNativeVariantForObject<ushort>(99, pNative);
+ ushort actual = Marshal.GetObjectForNativeVariant<ushort>(pNative);
+ Assert.Equal(99, actual);
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(pNative);
+ }
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public static void CharType()
+ {
+ // GetNativeVariantForObject supports char, but internally recognizes it the same as ushort
+ // because the native variant type uses mscorlib type VarEnum to store what type it contains.
+ // To get back the original char, use GetObjectForNativeVariant<ushort> and cast to char.
+ Variant v = new Variant();
+ IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
+ try
+ {
+ Marshal.GetNativeVariantForObject<char>('a', pNative);
+ ushort actual = Marshal.GetObjectForNativeVariant<ushort>(pNative);
+ char actualChar = (char)actual;
+ Assert.Equal('a', actualChar);
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(pNative);
+ }
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public static void CharTypeNegative()
+ {
+ // While GetNativeVariantForObject supports taking chars, GetObjectForNativeVariant will
+ // never return a char. The internal type is ushort, as mentioned above. This behavior
+ // is the same on ProjectN and Desktop CLR.
+ Variant v = new Variant();
+ IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
+ try
+ {
+ Marshal.GetNativeVariantForObject<char>('a', pNative);
+ Assert.Throws<InvalidCastException>(() => Marshal.GetObjectForNativeVariant<char>(pNative));
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(pNative);
+ }
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public static void StringType()
+ {
+ Variant v = new Variant();
+ IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
+ try
+ {
+ Marshal.GetNativeVariantForObject<string>("99", pNative);
+ string actual = Marshal.GetObjectForNativeVariant<string>(pNative);
+ Assert.Equal("99", actual);
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(pNative);
+ }
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public static void DoubleType()
+ {
+ Variant v = new Variant();
+ IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
+ try
+ {
+ Marshal.GetNativeVariantForObject<double>(3.14, pNative);
+ double actual = Marshal.GetObjectForNativeVariant<double>(pNative);
+ Assert.Equal(3.14, actual);
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(pNative);
+ }
+}
+#pragma warning restore 618
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+ public class GetObjectForNativeVariantTests
+ {
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Record
+ {
+ private IntPtr _record;
+ private IntPtr _recordInfo;
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ public struct UnionTypes
+ {
+ [FieldOffset(0)] internal SByte _i1;
+ [FieldOffset(0)] internal Int16 _i2;
+ [FieldOffset(0)] internal Int32 _i4;
+ [FieldOffset(0)] internal Int64 _i8;
+ [FieldOffset(0)] internal Byte _ui1;
+ [FieldOffset(0)] internal UInt16 _ui2;
+ [FieldOffset(0)] internal UInt32 _ui4;
+ [FieldOffset(0)] internal UInt64 _ui8;
+ [FieldOffset(0)] internal Int32 _int;
+ [FieldOffset(0)] internal UInt32 _uint;
+ [FieldOffset(0)] internal Single _r4;
+ [FieldOffset(0)] internal Double _r8;
+ [FieldOffset(0)] internal Int64 _cy;
+ [FieldOffset(0)] internal double _date;
+ [FieldOffset(0)] internal IntPtr _bstr;
+ [FieldOffset(0)] internal IntPtr _unknown;
+ [FieldOffset(0)] internal IntPtr _dispatch;
+ [FieldOffset(0)] internal IntPtr _pvarVal;
+ [FieldOffset(0)] internal IntPtr _byref;
+ [FieldOffset(0)] internal Record _record;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct TypeUnion
+ {
+ public ushort vt;
+ public ushort wReserved1;
+ public ushort wReserved2;
+ public ushort wReserved3;
+ public UnionTypes _unionTypes;
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ internal struct Variant
+ {
+ [FieldOffset(0)] public TypeUnion m_Variant;
+ [FieldOffset(0)] public decimal m_decimal;
+ }
+
+#pragma warning disable 618
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public static void NullParameter()
+ {
+ AssertExtensions.Throws<ArgumentNullException>("pSrcNativeVariant", () => Marshal.GetObjectForNativeVariant(IntPtr.Zero));
+ AssertExtensions.Throws<ArgumentNullException>("pSrcNativeVariant", () => Marshal.GetObjectForNativeVariant<int>(IntPtr.Zero));
+ }
+
+ [DllImport(@"oleaut32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
+ static extern Int32 VariantClear(IntPtr pvarg);
+
+ private static void DeleteVariant(IntPtr pVariant)
+ {
+ VariantClear(pVariant);
+ Marshal.FreeHGlobal(pVariant);
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public static void DecimalType()
+ {
+ Variant v = new Variant();
+ IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
+ try
+ {
+ Marshal.GetNativeVariantForObject(3.14m, pNative);
+ decimal d = Marshal.GetObjectForNativeVariant<decimal>(pNative);
+ Assert.Equal(3.14m, d);
+ }
+ finally
+ {
+ DeleteVariant(pNative);
+ }
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public static void PrimitiveType()
+ {
+ Variant v = new Variant();
+ IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
+ try
+ {
+ Marshal.GetNativeVariantForObject<ushort>(99, pNative);
+ ushort actual = Marshal.GetObjectForNativeVariant<ushort>(pNative);
+ Assert.Equal(99, actual);
+ }
+ finally
+ {
+ DeleteVariant(pNative);
+ }
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public static void StringType()
+ {
+ Variant v = new Variant();
+ IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
+ try
+ {
+ Marshal.GetNativeVariantForObject<string>("99", pNative);
+ string actual = Marshal.GetObjectForNativeVariant<string>(pNative);
+ Assert.Equal("99", actual);
+ }
+ finally
+ {
+ DeleteVariant(pNative);
+ }
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public static void DoubleType()
+ {
+ Variant v = new Variant();
+ IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
+ try
+ {
+ Marshal.GetNativeVariantForObject<double>(3.14, pNative);
+ double actual = Marshal.GetObjectForNativeVariant<double>(pNative);
+ Assert.Equal(3.14, actual);
+ }
+ finally
+ {
+ DeleteVariant(pNative);
+ }
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public static void IUnknownType()
+ {
+ Variant v = new Variant();
+ object obj = new object();
+
+ // Technically we don't need this - but this is necessary for forcing
+ // COM initialization
+ IntPtr pUnk = Marshal.GetIUnknownForObject(obj);
+ IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
+ try
+ {
+ Marshal.GetNativeVariantForObject<object>(obj, pNative);
+ object actual = Marshal.GetObjectForNativeVariant<object>(pNative);
+ Assert.Equal(obj, actual);
+ }
+ finally
+ {
+ Marshal.Release(pUnk);
+ DeleteVariant(pNative);
+ }
+ }
+#pragma warning restore 618
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+ public class GetObjectsForNativeVariantsTests
+ {
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Record
+ {
+ private IntPtr _record;
+ private IntPtr _recordInfo;
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ public struct UnionTypes
+ {
+ [FieldOffset(0)] internal SByte _i1;
+ [FieldOffset(0)] internal Int16 _i2;
+ [FieldOffset(0)] internal Int32 _i4;
+ [FieldOffset(0)] internal Int64 _i8;
+ [FieldOffset(0)] internal Byte _ui1;
+ [FieldOffset(0)] internal UInt16 _ui2;
+ [FieldOffset(0)] internal UInt32 _ui4;
+ [FieldOffset(0)] internal UInt64 _ui8;
+ [FieldOffset(0)] internal Int32 _int;
+ [FieldOffset(0)] internal UInt32 _uint;
+ [FieldOffset(0)] internal Single _r4;
+ [FieldOffset(0)] internal Double _r8;
+ [FieldOffset(0)] internal Int64 _cy;
+ [FieldOffset(0)] internal double _date;
+ [FieldOffset(0)] internal IntPtr _bstr;
+ [FieldOffset(0)] internal IntPtr _unknown;
+ [FieldOffset(0)] internal IntPtr _dispatch;
+ [FieldOffset(0)] internal IntPtr _pvarVal;
+ [FieldOffset(0)] internal IntPtr _byref;
+ [FieldOffset(0)] internal Record _record;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct TypeUnion
+ {
+ public ushort vt;
+ public ushort wReserved1;
+ public ushort wReserved2;
+ public ushort wReserved3;
+ public UnionTypes _unionTypes;
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ internal struct Variant
+ {
+ [FieldOffset(0)] public TypeUnion m_Variant;
+ [FieldOffset(0)] public decimal m_decimal;
+ }
+#pragma warning disable 618
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public static void NullParameter()
+ {
+ AssertExtensions.Throws<ArgumentNullException>("aSrcNativeVariant", () => Marshal.GetObjectsForNativeVariants(IntPtr.Zero, 10));
+ Assert.Throws<ArgumentOutOfRangeException>("cVars", () => Marshal.GetObjectsForNativeVariants<int>(new IntPtr(100), -1));
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public void SByteType()
+ {
+ Variant v = new Variant();
+
+ IntPtr pNative = Marshal.AllocHGlobal(2 * Marshal.SizeOf(v));
+ try
+ {
+ Marshal.GetNativeVariantForObject<sbyte>(99, pNative);
+ Marshal.GetNativeVariantForObject<sbyte>(100, pNative + Marshal.SizeOf(v));
+
+ sbyte[] actual = Marshal.GetObjectsForNativeVariants<sbyte>(pNative, 2);
+ Assert.Equal(99, actual[0]);
+ Assert.Equal(100, actual[1]);
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(pNative);
+ }
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public void ByteType()
+ {
+ Variant v = new Variant();
+
+ IntPtr pNative = Marshal.AllocHGlobal(2 * Marshal.SizeOf(v));
+ try
+ {
+ Marshal.GetNativeVariantForObject<byte>(99, pNative);
+ Marshal.GetNativeVariantForObject<byte>(100, pNative + Marshal.SizeOf(v));
+
+ byte[] actual = Marshal.GetObjectsForNativeVariants<byte>(pNative, 2);
+ Assert.Equal(99, actual[0]);
+ Assert.Equal(100, actual[1]);
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(pNative);
+ }
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public void DoubleType()
+ {
+ Variant v = new Variant();
+
+ IntPtr pNative = Marshal.AllocHGlobal(2 * Marshal.SizeOf(v));
+ try
+ {
+ Marshal.GetNativeVariantForObject<double>(99, pNative);
+ Marshal.GetNativeVariantForObject<double>(100, pNative + Marshal.SizeOf(v));
+
+ double[] actual = Marshal.GetObjectsForNativeVariants<double>(pNative, 2);
+ Assert.Equal(99, actual[0]);
+ Assert.Equal(100, actual[1]);
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(pNative);
+ }
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public void ShortType()
+ {
+ Variant v = new Variant();
+
+ IntPtr pNative = Marshal.AllocHGlobal(2 * Marshal.SizeOf(v));
+ try
+ {
+ Marshal.GetNativeVariantForObject<short>(99, pNative);
+ Marshal.GetNativeVariantForObject<short>(100, pNative + Marshal.SizeOf(v));
+
+ short[] actual = Marshal.GetObjectsForNativeVariants<short>(pNative, 2);
+ Assert.Equal(99, actual[0]);
+ Assert.Equal(100, actual[1]);
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(pNative);
+ }
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public void UshortType()
+ {
+ Variant v = new Variant();
+
+ IntPtr pNative = Marshal.AllocHGlobal(2 * Marshal.SizeOf(v));
+ try
+ {
+ Marshal.GetNativeVariantForObject<ushort>(99, pNative);
+ Marshal.GetNativeVariantForObject<ushort>(100, pNative + Marshal.SizeOf(v));
+
+ ushort[] actual = Marshal.GetObjectsForNativeVariants<ushort>(pNative, 2);
+ Assert.Equal(99, actual[0]);
+ Assert.Equal(100, actual[1]);
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(pNative);
+ }
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public void IntType()
+ {
+ Variant v = new Variant();
+
+ IntPtr pNative = Marshal.AllocHGlobal(2 * Marshal.SizeOf(v));
+ try
+ {
+ Marshal.GetNativeVariantForObject<int>(99, pNative);
+ Marshal.GetNativeVariantForObject<int>(100, pNative + Marshal.SizeOf(v));
+
+ int[] actual = Marshal.GetObjectsForNativeVariants<int>(pNative, 2);
+ Assert.Equal(99, actual[0]);
+ Assert.Equal(100, actual[1]);
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(pNative);
+ }
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public void UIntType()
+ {
+ Variant v = new Variant();
+
+ IntPtr pNative = Marshal.AllocHGlobal(2 * Marshal.SizeOf(v));
+ try
+ {
+ Marshal.GetNativeVariantForObject<uint>(99, pNative);
+ Marshal.GetNativeVariantForObject<uint>(100, pNative + Marshal.SizeOf(v));
+
+ uint[] actual = Marshal.GetObjectsForNativeVariants<uint>(pNative, 2);
+ Assert.Equal<uint>(99, actual[0]);
+ Assert.Equal<uint>(100, actual[1]);
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(pNative);
+ }
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public void LongType()
+ {
+ Variant v = new Variant();
+
+ IntPtr pNative = Marshal.AllocHGlobal(2 * Marshal.SizeOf(v));
+ try
+ {
+ Marshal.GetNativeVariantForObject<long>(99, pNative);
+ Marshal.GetNativeVariantForObject<long>(100, pNative + Marshal.SizeOf(v));
+
+ long[] actual = Marshal.GetObjectsForNativeVariants<long>(pNative, 2);
+ Assert.Equal(99, actual[0]);
+ Assert.Equal(100, actual[1]);
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(pNative);
+ }
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public void ULongType()
+ {
+ Variant v = new Variant();
+
+ IntPtr pNative = Marshal.AllocHGlobal(2 * Marshal.SizeOf(v));
+ try
+ {
+ Marshal.GetNativeVariantForObject<ulong>(99, pNative);
+ Marshal.GetNativeVariantForObject<ulong>(100, pNative + Marshal.SizeOf(v));
+
+ ulong[] actual = Marshal.GetObjectsForNativeVariants<ulong>(pNative, 2);
+ Assert.Equal<ulong>(99, actual[0]);
+ Assert.Equal<ulong>(100, actual[1]);
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(pNative);
+ }
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public void FloatType()
+ {
+ Variant v = new Variant();
+
+ IntPtr pNative = Marshal.AllocHGlobal(2 * Marshal.SizeOf(v));
+ try
+ {
+ Marshal.GetNativeVariantForObject<float>(99, pNative);
+ Marshal.GetNativeVariantForObject<float>(100, pNative + Marshal.SizeOf(v));
+
+ float[] actual = Marshal.GetObjectsForNativeVariants<float>(pNative, 2);
+ Assert.Equal(99, actual[0]);
+ Assert.Equal(100, actual[1]);
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(pNative);
+ }
+ }
+
+#pragma warning restore 618
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+ public class OffsetOfTests
+ {
+ [Fact]
+ public static void NullParameter()
+ {
+ Assert.Throws<ArgumentNullException>(() => Marshal.OffsetOf(null, null));
+ Assert.Throws<ArgumentNullException>(() => Marshal.OffsetOf(new object().GetType(), null));
+ Assert.Throws<ArgumentNullException>(() => Marshal.OffsetOf(null, "abcd"));
+ }
+
+ [Fact]
+ public void NonExistField()
+ {
+ Assert.Throws<ArgumentException>(() => Marshal.OffsetOf(typeof(NonExistField), "NonExistField"));
+ }
+
+ [Fact]
+ public void NoLayoutClass()
+ {
+ Assert.Throws<ArgumentException>(() => Marshal.OffsetOf(typeof(NoLayoutPoint), "x"));
+ }
+
+ [Fact]
+ public void StructField()
+ {
+ Assert.Equal(new IntPtr(4), Marshal.OffsetOf(typeof(SomeStruct), "var"));
+ }
+
+ [Fact]
+ public void ClassExplicitField()
+ {
+ Assert.Equal(new IntPtr(0), Marshal.OffsetOf(typeof(MySystemTime), "wYear"));
+ Assert.Equal(new IntPtr(8), Marshal.OffsetOf(typeof(MySystemTime), "wHour"));
+ Assert.Equal(new IntPtr(14), Marshal.OffsetOf(typeof(MySystemTime), "wMilliseconds"));
+ }
+
+ [Fact]
+ public void ClassSequentialField()
+ {
+ Assert.Equal(new IntPtr(0), Marshal.OffsetOf(typeof(MyPoint), "x"));
+ Assert.Equal(new IntPtr(4), Marshal.OffsetOf(typeof(MyPoint), "y"));
+ }
+
+ [Fact]
+ public void TestExplicitLayout()
+ {
+ Type t = typeof(ExplicitLayoutTest);
+ Assert.Equal(56, Marshal.SizeOf(t));
+ Assert.Equal(new IntPtr(0), Marshal.OffsetOf(t, "m_short1"));
+ Assert.Equal(new IntPtr(2), Marshal.OffsetOf(t, "m_short2"));
+
+ Assert.Equal(new IntPtr(4), Marshal.OffsetOf(t, "union1_byte1"));
+ Assert.Equal(new IntPtr(5), Marshal.OffsetOf(t, "union1_byte2"));
+ Assert.Equal(new IntPtr(6), Marshal.OffsetOf(t, "union1_short1"));
+ Assert.Equal(new IntPtr(8), Marshal.OffsetOf(t, "union1_int1"));
+ Assert.Equal(new IntPtr(12), Marshal.OffsetOf(t, "union1_int2"));
+ Assert.Equal(new IntPtr(16), Marshal.OffsetOf(t, "union1_double1"));
+
+ Assert.Equal(new IntPtr(4), Marshal.OffsetOf(t, "union2_ushort1"));
+ Assert.Equal(new IntPtr(6), Marshal.OffsetOf(t, "union2_ushort2"));
+ Assert.Equal(new IntPtr(8), Marshal.OffsetOf(t, "union3_int1"));
+ Assert.Equal(new IntPtr(8), Marshal.OffsetOf(t, "union3_decimal1"));
+
+ Assert.Equal(new IntPtr(24), Marshal.OffsetOf(t, "m_ushort1"));
+ Assert.Equal(new IntPtr(32), Marshal.OffsetOf(t, "m_decimal1"));
+ Assert.Equal(new IntPtr(48), Marshal.OffsetOf(t, "m_char1"));
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public void TestFieldAlignment_Windows()
+ {
+ Type t = typeof(FieldAlignmentTest);
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || (RuntimeInformation.ProcessArchitecture != Architecture.X86))
+ {
+ Assert.Equal(80, Marshal.SizeOf(t));
+ }
+ else
+ {
+ Assert.Equal(72, Marshal.SizeOf(t));
+ }
+
+ Assert.Equal(new IntPtr(0), Marshal.OffsetOf(t, "m_byte1"));
+ Assert.Equal(new IntPtr(2), Marshal.OffsetOf(t, "m_short1"));
+ Assert.Equal(new IntPtr(4), Marshal.OffsetOf(t, "m_short2"));
+ Assert.Equal(new IntPtr(8), Marshal.OffsetOf(t, "m_int1"));
+ Assert.Equal(new IntPtr(12), Marshal.OffsetOf(t, "m_byte2"));
+ Assert.Equal(new IntPtr(16), Marshal.OffsetOf(t, "m_int2"));
+
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || (RuntimeInformation.ProcessArchitecture != Architecture.X86))
+ {
+ Assert.Equal(new IntPtr(24), Marshal.OffsetOf(t, "m_double1"));
+ Assert.Equal(new IntPtr(32), Marshal.OffsetOf(t, "m_char1"));
+ Assert.Equal(new IntPtr(33), Marshal.OffsetOf(t, "m_char2"));
+ Assert.Equal(new IntPtr(34), Marshal.OffsetOf(t, "m_char3"));
+ Assert.Equal(new IntPtr(40), Marshal.OffsetOf(t, "m_double2"));
+ Assert.Equal(new IntPtr(48), Marshal.OffsetOf(t, "m_byte3"));
+ Assert.Equal(new IntPtr(49), Marshal.OffsetOf(t, "m_byte4"));
+ Assert.Equal(new IntPtr(56), Marshal.OffsetOf(t, "m_decimal1"));
+ Assert.Equal(new IntPtr(72), Marshal.OffsetOf(t, "m_char4"));
+ }
+ else
+ {
+ Assert.Equal(new IntPtr(20), Marshal.OffsetOf(t, "m_double1"));
+ Assert.Equal(new IntPtr(28), Marshal.OffsetOf(t, "m_char1"));
+ Assert.Equal(new IntPtr(29), Marshal.OffsetOf(t, "m_char2"));
+ Assert.Equal(new IntPtr(30), Marshal.OffsetOf(t, "m_char3"));
+ Assert.Equal(new IntPtr(32), Marshal.OffsetOf(t, "m_double2"));
+ Assert.Equal(new IntPtr(40), Marshal.OffsetOf(t, "m_byte3"));
+ Assert.Equal(new IntPtr(41), Marshal.OffsetOf(t, "m_byte4"));
+ Assert.Equal(new IntPtr(48), Marshal.OffsetOf(t, "m_decimal1"));
+ Assert.Equal(new IntPtr(64), Marshal.OffsetOf(t, "m_char4"));
+ }
+ }
+
+ [Fact]
+ public void TestFieldAlignment_Decimal()
+ {
+ Type t = typeof(FieldAlignmentTest_Decimal);
+
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || (RuntimeInformation.ProcessArchitecture != Architecture.X86))
+ {
+ Assert.Equal(96, Marshal.SizeOf(t));
+ }
+ else
+ {
+ Assert.Equal(88, Marshal.SizeOf(t));
+ }
+
+ Assert.Equal(new IntPtr(0), Marshal.OffsetOf(t, "b"));
+ Assert.Equal(new IntPtr(8), Marshal.OffsetOf(t, "p"));
+
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || (RuntimeInformation.ProcessArchitecture != Architecture.X86))
+ {
+ Assert.Equal(new IntPtr(88), Marshal.OffsetOf(t, "s"));
+ }
+ else
+ {
+ Assert.Equal(new IntPtr(80), Marshal.OffsetOf(t, "s"));
+ }
+ }
+
+ [Fact]
+ public void TestFieldAlignment_Guid()
+ {
+ Type t = typeof(FieldAlignmentTest_Guid);
+ Assert.Equal(24, Marshal.SizeOf(t));
+
+ Assert.Equal(new IntPtr(0), Marshal.OffsetOf(t, "b"));
+ Assert.Equal(new IntPtr(4), Marshal.OffsetOf(t, "g"));
+ Assert.Equal(new IntPtr(20), Marshal.OffsetOf(t, "s"));
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public void TestFieldAlignment_Variant()
+ {
+ Type t = typeof(FieldAlignmentTest_Variant);
+
+ Assert.Equal(new IntPtr(0), Marshal.OffsetOf(t, "b"));
+ Assert.Equal(new IntPtr(8), Marshal.OffsetOf(t, "v"));
+
+ if (IntPtr.Size == 4)
+ {
+ Assert.Equal(new IntPtr(24), Marshal.OffsetOf(t, "s"));
+ Assert.Equal(32, Marshal.SizeOf(t));
+ }
+ else if (IntPtr.Size == 8)
+ {
+ Assert.Equal(new IntPtr(32), Marshal.OffsetOf(t, "s"));
+ Assert.Equal(40, Marshal.SizeOf(t));
+ }
+ else
+ {
+ Assert.True(false, string.Format("Unexpected value '{0}' for IntPtr.Size", IntPtr.Size));
+ }
+ }
+
+ [Fact]
+ public void NonGenericOffEqualsGenericOffset()
+ {
+ IntPtr nonGenericOffsetCall = Marshal.OffsetOf(typeof(SomeStruct), "var");
+ IntPtr genericOffsetCall = Marshal.OffsetOf<SomeStruct>("var");
+ Assert.Equal(nonGenericOffsetCall, genericOffsetCall);
+
+ Assert.Throws<ArgumentException>(() => Marshal.OffsetOf(typeof(StructWithFxdLPSTRSAFld), "Arr"));
+ }
+ }
+#pragma warning disable 169, 649, 618
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructWithFxdLPSTRSAFld
+ {
+ [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.LPStr, SizeConst = 0)]
+ public String[] Arr;
+ }
+
+ public struct SomeStruct
+ {
+ public bool p;
+ public int var;
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ public class MySystemTime
+ {
+ [FieldOffset(0)]
+ public ushort wYear;
+ [FieldOffset(2)]
+ public ushort wMonth;
+ [FieldOffset(4)]
+ public ushort wDayOfWeek;
+ [FieldOffset(6)]
+ public ushort wDay;
+ [FieldOffset(8)]
+ public ushort wHour;
+ [FieldOffset(10)]
+ public ushort wMinute;
+ [FieldOffset(12)]
+ public ushort wSecond;
+ [FieldOffset(14)]
+ public ushort wMilliseconds;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public class MyPoint
+ {
+ public int x;
+ public int y;
+ }
+
+ public class NoLayoutPoint
+ {
+ public int x;
+ public int y;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public class NonExistField
+ {
+
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ internal struct ExplicitLayoutTest
+ {
+ [FieldOffset(0)]
+ public short m_short1; // 2 bytes
+ [FieldOffset(2)]
+ public short m_short2; // 2 bytes
+
+ [FieldOffset(4)]
+ public byte union1_byte1; // 1 byte
+ [FieldOffset(5)]
+ public byte union1_byte2; // 1 byte
+ [FieldOffset(6)]
+ public short union1_short1; // 2 bytes
+ [FieldOffset(8)]
+ public Int32 union1_int1; // 4 bytes
+ [FieldOffset(12)]
+ public Int32 union1_int2; // 4 bytes
+ [FieldOffset(16)]
+ public double union1_double1; // 8 bytes
+
+ [FieldOffset(4)]
+ public ushort union2_ushort1; // 2 bytes
+ [FieldOffset(6)]
+ public ushort union2_ushort2; // 2 bytes
+ [FieldOffset(8)]
+ public Int32 union3_int1; // 4 bytes
+ [FieldOffset(8)]
+ public decimal union3_decimal1; // 16 bytes
+
+ [FieldOffset(24)]
+ public ushort m_ushort1; // 2 bytes
+ // 6 bytes of padding
+
+ [FieldOffset(32)]
+ public decimal m_decimal1; // 16 bytes
+
+ [FieldOffset(48)]
+ public char m_char1; // 1 byte
+ // 7 bytes of padding
+ }
+
+ internal struct FieldAlignmentTest
+ {
+ public byte m_byte1; // 1 byte
+ // 1 byte of padding
+
+ public short m_short1; // 2 bytes
+ public short m_short2; // 2 bytes
+ // 2 bytes of padding
+
+ public Int32 m_int1; // 4 bytes
+ public byte m_byte2; // 1 byte
+ // 3 bytes of padding
+
+ public Int32 m_int2; // 4 bytes
+ // 4 bytes of padding (0 bytes on x86/Unix according System V ABI as double 4-byte aligned)
+
+ public double m_double1; // 8 bytes
+ public char m_char1; // 1 byte
+ public char m_char2; // 1 byte
+ public char m_char3; // 1 byte
+ // 5 bytes of padding (1 byte on x86/Unix according System V ABI as double 4-byte aligned)
+
+ public double m_double2; // 8 bytes
+ public byte m_byte3; // 1 byte
+ public byte m_byte4; // 1 byte
+ // 6 bytes of padding
+
+ public decimal m_decimal1; // 16 bytes
+ public char m_char4; // 1 byte
+ // 7 bytes of padding
+ }
+ struct FieldAlignmentTest_Decimal
+ {
+ public byte b; // 1 byte
+ // 7 bytes of padding
+
+ // The largest field in below struct is decimal (16 bytes wide).
+ // However, alignment requirement for the below struct should be only 8 bytes (not 16).
+ // This is because unlike fields of other types well known to mcg (like long, char etc.)
+ // which need to be aligned according to their byte size, decimal is really a struct
+ // with 8 byte alignment requirement.
+ public FieldAlignmentTest p; // 80 bytes (72 bytes on x86/Unix)
+
+ public short s; // 2 bytes
+ // 6 bytes of padding
+ }
+
+ struct FieldAlignmentTest_Guid
+ {
+ public byte b; // 1 byte
+ // 3 bytes of padding
+
+ // Guid is really a struct with 4 byte alignment requirement (which is less than its byte size of 16 bytes).
+ public Guid g; // 16 bytes
+
+ public short s; // 2 bytes
+ // 2 bytes of padding
+ }
+
+ struct FieldAlignmentTest_Variant
+ {
+ public byte b; // 1 byte
+ // 7 bytes of padding
+
+ // Using [MarshalAs(UnmanagedType.Struct)] means that the Variant type will be used for field 'v' on native side.
+ // Variant is really a struct with 8 byte alignment requirement (which is less than its byte size of 24 / 16 bytes).
+ [MarshalAs(UnmanagedType.Struct)]
+ public object v; // 16 bytes on 32-bit, 24 bytes on 64-bit
+
+ public short s; // 2 bytes
+ // 6 bytes of padding
+ };
+#pragma warning restore 169, 649, 618
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+ public class PtrToStringTests
+ {
+ [Fact]
+ public void PtrToStringAnsi()
+ {
+ AssertExtensions.Throws<ArgumentNullException>("ptr", () => Marshal.PtrToStringAnsi(IntPtr.Zero, 123));
+ Assert.Throws<ArgumentException>(() => Marshal.PtrToStringAnsi(new IntPtr(123), -77));
+ }
+
+ [Fact]
+ public void PtrToStringUni()
+ {
+ AssertExtensions.Throws<ArgumentNullException>("ptr", () => Marshal.PtrToStringUni(IntPtr.Zero, 123));
+ Assert.Throws<ArgumentException>(() => Marshal.PtrToStringUni(new IntPtr(123), -77));
+ }
+
+ [Fact]
+ public void PtrToStringAuto()
+ {
+ AssertExtensions.Throws<ArgumentNullException>("ptr", () => Marshal.PtrToStringAuto(IntPtr.Zero, 123));
+ Assert.Throws<ArgumentException>(() => Marshal.PtrToStringAuto(new IntPtr(123), -77));
+ }
+
+ [Fact]
+ public void PtrToStringBSTR()
+ {
+ AssertExtensions.Throws<ArgumentNullException>("ptr", () => Marshal.PtrToStringBSTR(IntPtr.Zero));
+ }
+
+#if netcoreapp
+ [Fact]
+ public void PtrToStringUTF8()
+ {
+ Assert.Null(Marshal.PtrToStringUTF8(IntPtr.Zero, 123));
+ Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.PtrToStringUTF8(new IntPtr(123), -77));
+ }
+#endif
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+ public class PtrToStructureTests
+ {
+ [StructLayout(LayoutKind.Sequential)]
+ public struct SomeTestStruct
+ {
+ public int i;
+ public String s;
+ }
+
+ [Fact]
+ public void PtrToStructureTest()
+ {
+ IntPtr ip;
+ SomeTestStruct someTestStruct = new SomeTestStruct();
+
+ ip = IntPtr.Zero;
+ AssertExtensions.Throws<ArgumentNullException>("ptr", () => Marshal.PtrToStructure(ip, someTestStruct));
+
+ ip = new IntPtr(123);
+ AssertExtensions.Throws<ArgumentNullException>("structureType", () => Marshal.PtrToStructure(ip, null));
+
+ ip = new IntPtr(123);
+ Assert.Throws<ArgumentException>(() => Marshal.PtrToStructure<SomeTestStruct>(ip, someTestStruct));
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+ public class ByteTests
+ {
+ public static readonly object[][] ArrayData =
+ {
+ new object[] { new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, byte.MaxValue } }
+ };
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void NullValue_ThrowsException(byte[] TestValues)
+ {
+ Exception e;
+
+ e = Record.Exception(() => Marshal.ReadByte(IntPtr.Zero));
+ Assert.True(e is AccessViolationException || e is NullReferenceException);
+
+ e = Record.Exception(() => Marshal.ReadByte(IntPtr.Zero, 2));
+ Assert.True(e is AccessViolationException || e is NullReferenceException);
+
+ e = Record.Exception(() => Marshal.WriteByte(IntPtr.Zero, TestValues[0]));
+ Assert.True(e is AccessViolationException || e is NullReferenceException);
+
+ e = Record.Exception(() => Marshal.WriteByte(IntPtr.Zero, 2, TestValues[0]));
+ Assert.True(e is AccessViolationException || e is NullReferenceException);
+ }
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void ReadWriteRoundTrip(byte[] TestValues)
+ {
+ int sizeOfArray = Marshal.SizeOf(TestValues[0]) * TestValues.Length;
+
+ IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+ try
+ {
+ Marshal.WriteByte(ptr, TestValues[0]);
+
+ for (int i = 1; i < TestValues.Length; i++)
+ {
+ Marshal.WriteByte(ptr, i * Marshal.SizeOf(TestValues[0]), TestValues[i]);
+ }
+
+ byte value = Marshal.ReadByte(ptr);
+ Assert.Equal(TestValues[0], value);
+
+ for (int i = 1; i < TestValues.Length; i++)
+ {
+ value = Marshal.ReadByte(ptr, i * Marshal.SizeOf(TestValues[0]));
+ Assert.Equal(TestValues[i], value);
+ }
+ }
+ finally
+ {
+ Marshal.FreeCoTaskMem(ptr);
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+ public class Int16Tests
+ {
+ public static readonly object[][] ArrayData =
+ {
+ new object[] { new short[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, short.MaxValue } }
+ };
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void NullValue_ThrowsException(short[] TestValues)
+ {
+ Exception e;
+
+ e = Record.Exception(() => Marshal.ReadInt16(IntPtr.Zero));
+ Assert.True(e is AccessViolationException || e is NullReferenceException);
+
+ e = Record.Exception(() => Marshal.ReadInt16(IntPtr.Zero, 2));
+ Assert.True(e is AccessViolationException || e is NullReferenceException);
+
+ e = Record.Exception(() => Marshal.WriteInt16(IntPtr.Zero, TestValues[0]));
+ Assert.True(e is AccessViolationException || e is NullReferenceException);
+
+ e = Record.Exception(() => Marshal.WriteInt16(IntPtr.Zero, 2, TestValues[0]));
+ Assert.True(e is AccessViolationException || e is NullReferenceException);
+ }
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void ReadWriteRoundTrip(short[] TestValues)
+ {
+ int sizeOfArray = Marshal.SizeOf(TestValues[0]) * TestValues.Length;
+
+ IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+ try
+ {
+ Marshal.WriteInt16(ptr, TestValues[0]);
+
+ for (int i = 1; i < TestValues.Length; i++)
+ {
+ Marshal.WriteInt16(ptr, i * Marshal.SizeOf(TestValues[0]), TestValues[i]);
+ }
+
+ short value = Marshal.ReadInt16(ptr);
+ Assert.Equal(TestValues[0], value);
+
+ for (int i = 1; i < TestValues.Length; i++)
+ {
+ value = Marshal.ReadInt16(ptr, i * Marshal.SizeOf(TestValues[0]));
+ Assert.Equal(TestValues[i], value);
+ }
+ }
+ finally
+ {
+ Marshal.FreeCoTaskMem(ptr);
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+ public class Int32Tests
+ {
+ public static readonly object[][] ArrayData =
+ {
+ new object[] { new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, int.MaxValue } }
+ };
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void NullValue_ThrowsException(int[] TestValues)
+ {
+ Exception e;
+
+ e = Record.Exception(() => Marshal.ReadInt32(IntPtr.Zero));
+ Assert.True(e is AccessViolationException || e is NullReferenceException);
+
+ e = Record.Exception(() => Marshal.ReadInt32(IntPtr.Zero, 2));
+ Assert.True(e is AccessViolationException || e is NullReferenceException);
+
+ e = Record.Exception(() => Marshal.WriteInt32(IntPtr.Zero, TestValues[0]));
+ Assert.True(e is AccessViolationException || e is NullReferenceException);
+
+ e = Record.Exception(() => Marshal.WriteInt32(IntPtr.Zero, 2, TestValues[0]));
+ Assert.True(e is AccessViolationException || e is NullReferenceException);
+ }
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void ReadWriteRoundTrip(int[] TestValues)
+ {
+ int sizeOfArray = Marshal.SizeOf(TestValues[0]) * TestValues.Length;
+
+ IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+ try
+ {
+ Marshal.WriteInt32(ptr, TestValues[0]);
+
+ for (int i = 1; i < TestValues.Length; i++)
+ {
+ Marshal.WriteInt32(ptr, i * Marshal.SizeOf(TestValues[0]), TestValues[i]);
+ }
+
+ int value = Marshal.ReadInt32(ptr);
+ Assert.Equal(TestValues[0], value);
+
+ for (int i = 1; i < TestValues.Length; i++)
+ {
+ value = Marshal.ReadInt32(ptr, i * Marshal.SizeOf(TestValues[0]));
+ Assert.Equal(TestValues[i], value);
+ }
+ }
+ finally
+ {
+ Marshal.FreeCoTaskMem(ptr);
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+ public class Int64Tests
+ {
+ public static readonly object[][] ArrayData =
+ {
+ new object[] { new long[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, long.MaxValue } }
+ };
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void NullValue_ThrowsException(long[] TestValues)
+ {
+ Exception e;
+
+ e = Record.Exception(() => Marshal.ReadInt64(IntPtr.Zero));
+ Assert.True(e is AccessViolationException || e is NullReferenceException);
+
+ e = Record.Exception(() => Marshal.ReadInt64(IntPtr.Zero, 2));
+ Assert.True(e is AccessViolationException || e is NullReferenceException);
+
+ e = Record.Exception(() => Marshal.WriteInt64(IntPtr.Zero, TestValues[0]));
+ Assert.True(e is AccessViolationException || e is NullReferenceException);
+
+ e = Record.Exception(() => Marshal.WriteInt64(IntPtr.Zero, 2, TestValues[0]));
+ Assert.True(e is AccessViolationException || e is NullReferenceException);
+ }
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void ReadWriteRoundTrip(long[] TestValues)
+ {
+ int sizeOfArray = Marshal.SizeOf(TestValues[0]) * TestValues.Length;
+
+ IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+ try
+ {
+ Marshal.WriteInt64(ptr, TestValues[0]);
+
+ for (int i = 1; i < TestValues.Length; i++)
+ {
+ Marshal.WriteInt64(ptr, i * Marshal.SizeOf(TestValues[0]), TestValues[i]);
+ }
+
+ long value = Marshal.ReadInt64(ptr);
+ Assert.Equal(TestValues[0], value);
+
+ for (int i = 1; i < TestValues.Length; i++)
+ {
+ value = Marshal.ReadInt64(ptr, i * Marshal.SizeOf(TestValues[0]));
+ Assert.Equal(TestValues[i], value);
+ }
+ }
+ finally
+ {
+ Marshal.FreeCoTaskMem(ptr);
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+ public class IntPtrTests
+ {
+ public static readonly object[][] ArrayData =
+ {
+ new object[] { GenerateIntPtrArray() }
+ };
+
+ public static IntPtr[] GenerateIntPtrArray()
+ {
+ IntPtr[] testArray = new IntPtr[10];
+ for (int i = 0; i < testArray.Length; i++)
+ testArray[i] = new IntPtr(i);
+ return testArray;
+ }
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void NullValue_ThrowsException(IntPtr[] TestValues)
+ {
+ Exception e;
+
+ e = Record.Exception(() => Marshal.ReadIntPtr(IntPtr.Zero));
+ Assert.True(e is AccessViolationException || e is NullReferenceException);
+
+ e = Record.Exception(() => Marshal.ReadIntPtr(IntPtr.Zero, 2));
+ Assert.True(e is AccessViolationException || e is NullReferenceException);
+
+ e = Record.Exception(() => Marshal.WriteIntPtr(IntPtr.Zero, TestValues[0]));
+ Assert.True(e is AccessViolationException || e is NullReferenceException);
+
+ e = Record.Exception(() => Marshal.WriteIntPtr(IntPtr.Zero, 2, TestValues[0]));
+ Assert.True(e is AccessViolationException || e is NullReferenceException);
+ }
+
+ [Theory]
+ [MemberData(nameof(ArrayData))]
+ public void ReadWriteRoundTrip(IntPtr[] TestValues)
+ {
+ int sizeOfArray = Marshal.SizeOf(TestValues[0]) * TestValues.Length;
+
+ IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+ try
+ {
+ Marshal.WriteIntPtr(ptr, TestValues[0]);
+
+ for (int i = 1; i < TestValues.Length; i++)
+ {
+ Marshal.WriteIntPtr(ptr, i * Marshal.SizeOf(TestValues[0]), TestValues[i]);
+ }
+
+ IntPtr value = Marshal.ReadIntPtr(ptr);
+ Assert.Equal(TestValues[0], value);
+
+ for (int i = 1; i < TestValues.Length; i++)
+ {
+ value = Marshal.ReadIntPtr(ptr, i * Marshal.SizeOf(TestValues[0]));
+ Assert.Equal(TestValues[i], value);
+ }
+ }
+ finally
+ {
+ Marshal.FreeCoTaskMem(ptr);
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+ internal struct BlittableStruct
+ {
+ internal int _a;
+ internal int _b;
+ internal byte _c;
+ internal short _d;
+ internal IntPtr _p;
+ }
+
+ internal struct StructWithReferenceTypes
+ {
+ internal IntPtr _ptr;
+ internal string _str;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
+ internal int[] _byValArr;
+ }
+#pragma warning disable 618
+ public class ObjectTests
+ {
+ [Fact]
+ [ActiveIssue(30830, TargetFrameworkMonikers.NetFramework)]
+ public void NullValueArguments_ThrowsArgumentNullException()
+ {
+ AssertExtensions.Throws<ArgumentNullException>("ptr", () => { Marshal.WriteByte(null, 0, 0); });
+ AssertExtensions.Throws<ArgumentNullException>("ptr", () => { Marshal.WriteInt16(null, 0, 0); });
+ AssertExtensions.Throws<ArgumentNullException>("ptr", () => { Marshal.WriteInt32(null, 0, 0); });
+ AssertExtensions.Throws<ArgumentNullException>("ptr", () => { Marshal.WriteInt64(null, 0, 0); });
+ AssertExtensions.Throws<ArgumentNullException>("ptr", () => { Marshal.WriteIntPtr(null, 0, IntPtr.Zero); });
+ AssertExtensions.Throws<ArgumentNullException>("ptr", () => { Marshal.ReadByte(null, 0); });
+ AssertExtensions.Throws<ArgumentNullException>("ptr", () => { Marshal.ReadInt16(null, 0); });
+ AssertExtensions.Throws<ArgumentNullException>("ptr", () => { Marshal.ReadInt32(null, 0); });
+ AssertExtensions.Throws<ArgumentNullException>("ptr", () => { Marshal.ReadIntPtr(null, 0); });
+ }
+
+ [Fact]
+ public void TestBlittableStruct()
+ {
+ BlittableStruct blittableStruct = new BlittableStruct();
+ blittableStruct._a = 200;
+ blittableStruct._b = 300;
+ blittableStruct._c = 10;
+ blittableStruct._d = 123;
+ blittableStruct._p = new IntPtr(100);
+
+ object boxedBlittableStruct = (object)blittableStruct;
+
+ int offsetOfB = Marshal.OffsetOf<BlittableStruct>("_b").ToInt32();
+ int offsetOfC = Marshal.OffsetOf<BlittableStruct>("_c").ToInt32();
+ int offsetOfD = Marshal.OffsetOf<BlittableStruct>("_d").ToInt32();
+ int offsetOfP = Marshal.OffsetOf<BlittableStruct>("_p").ToInt32();
+
+ Assert.Equal(200, Marshal.ReadInt32(boxedBlittableStruct, 0));
+ Assert.Equal(300, Marshal.ReadInt32(boxedBlittableStruct, offsetOfB));
+ Assert.Equal(10, Marshal.ReadByte(boxedBlittableStruct, offsetOfC));
+ Assert.Equal(123, Marshal.ReadInt16(boxedBlittableStruct, offsetOfD));
+ Assert.Equal(new IntPtr(100), Marshal.ReadIntPtr(boxedBlittableStruct, offsetOfP));
+
+ Marshal.WriteInt32(boxedBlittableStruct, 0, 300);
+ Marshal.WriteInt32(boxedBlittableStruct, offsetOfB, 400);
+ Marshal.WriteByte(boxedBlittableStruct, offsetOfC, 20);
+ Marshal.WriteInt16(boxedBlittableStruct, offsetOfD, 144);
+
+ Marshal.WriteIntPtr(boxedBlittableStruct, offsetOfP, new IntPtr(500));
+
+ Assert.Equal(300, ((BlittableStruct)boxedBlittableStruct)._a);
+ Assert.Equal(400, ((BlittableStruct)boxedBlittableStruct)._b);
+ Assert.Equal(20, ((BlittableStruct)boxedBlittableStruct)._c);
+ Assert.Equal(144, ((BlittableStruct)boxedBlittableStruct)._d);
+ Assert.Equal(new IntPtr(500), ((BlittableStruct)boxedBlittableStruct)._p);
+ }
+
+ [Fact]
+ public void TestStructWithReferenceType()
+ {
+ StructWithReferenceTypes structWithReferenceTypes = new StructWithReferenceTypes();
+ structWithReferenceTypes._ptr = new IntPtr(100);
+ structWithReferenceTypes._str = "ABC";
+ structWithReferenceTypes._byValArr = new int[10] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+
+ object boxedStruct = (object)structWithReferenceTypes;
+
+ int offsetOfStr = Marshal.OffsetOf<StructWithReferenceTypes>("_str").ToInt32();
+ int offsetOfByValArr = Marshal.OffsetOf<StructWithReferenceTypes>("_byValArr").ToInt32();
+
+ Assert.Equal(100, Marshal.ReadInt32(boxedStruct, 0));
+ Assert.NotEqual(IntPtr.Zero, Marshal.ReadIntPtr(boxedStruct, offsetOfStr));
+ Assert.Equal(3, Marshal.ReadInt32(boxedStruct, offsetOfByValArr + sizeof(int) * 2));
+
+ Marshal.WriteInt32(boxedStruct, 0, 200);
+ Marshal.WriteInt32(boxedStruct, offsetOfByValArr + sizeof(int) * 9, 100);
+
+ Assert.Equal(new IntPtr(200), ((StructWithReferenceTypes)boxedStruct)._ptr);
+ Assert.Equal(100, ((StructWithReferenceTypes)boxedStruct)._byValArr[9]);
+ Assert.Equal(9, ((StructWithReferenceTypes)boxedStruct)._byValArr[8]);
+ Assert.Equal("ABC", ((StructWithReferenceTypes)boxedStruct)._str);
+ }
+ }
+#pragma warning restore 618
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+ public class SizeOfTests
+ {
+ public struct TestStructWithEnumArray
+ {
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+ public TestEnum[] ArrayOfEnum;
+ }
+
+ public enum TestEnum
+ {
+ red,
+ green,
+ blue
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct SomeTestStruct
+ {
+ public int i;
+ public String s;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct TestStructWithFxdLPSTRSAFld
+ {
+ [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.LPStr, SizeConst = 0)]
+ public String[] Arr;
+ }
+
+ [Fact]
+ public void SizeOfStructWithEnumArray()
+ {
+ TestStructWithEnumArray s = new TestStructWithEnumArray();
+ s.ArrayOfEnum = new TestEnum[3];
+ s.ArrayOfEnum[0] = TestEnum.red;
+ s.ArrayOfEnum[1] = TestEnum.green;
+ s.ArrayOfEnum[2] = TestEnum.blue;
+ int retsize = Marshal.SizeOf(s.GetType());
+ Assert.Equal(12, retsize);
+
+ retsize = 0;
+ retsize = Marshal.SizeOf(typeof(TestStructWithEnumArray));
+ int genericRetsize = Marshal.SizeOf<TestStructWithEnumArray>();
+ Assert.Equal(12, retsize);
+ Assert.Equal(retsize, genericRetsize);
+ }
+
+ [Fact]
+ public void SizeOfStructTest()
+ {
+ SomeTestStruct someTestStruct = new SomeTestStruct();
+ AssertExtensions.Throws<ArgumentNullException>("t", () => Marshal.SizeOf(null));
+ Assert.Throws<ArgumentException>(() => Marshal.SizeOf(typeof(TestStructWithFxdLPSTRSAFld)));
+ Marshal.SizeOf(someTestStruct.GetType());
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Linq;
+using Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+ public class StringMarshalingTests
+ {
+ private readonly String[] TestStrings = new String[] {
+ "", //Empty String
+ "Test String",
+ "A", //Single character string
+ string.Concat(Enumerable.Repeat("This is a very long string as it repeats itself. ", 13)),
+ "This \n is \n a \n multiline \n string",
+ "This \0 is \0 a \0 string \0 with \0 nulls",
+ "\0string",
+ "string\0",
+ "\0\0\0\0\0\0\0\0"
+ };
+
+ [Fact]
+ public void StringToBStrToString()
+ {
+ foreach (String ts in TestStrings)
+ {
+ IntPtr BStr = Marshal.StringToBSTR(ts);
+ try
+ {
+ String str = Marshal.PtrToStringBSTR(BStr);
+ Assert.Equal(ts, str);
+ }
+ finally
+ {
+ Marshal.FreeBSTR(BStr);
+ }
+ }
+ }
+
+ [Fact]
+ public void StringToCoTaskMemAnsiToString()
+ {
+ foreach (String ts in TestStrings)
+ {
+ if (ts.Contains("\0"))
+ continue; //Skip the string with nulls case
+
+ IntPtr AnsiStr = Marshal.StringToCoTaskMemAnsi(ts);
+ try
+ {
+ String str = Marshal.PtrToStringAnsi(AnsiStr);
+
+ Assert.Equal(ts, str);
+ if (ts.Length > 0)
+ {
+ String str2 = Marshal.PtrToStringAnsi(AnsiStr, ts.Length - 1);
+ Assert.Equal(ts.Substring(0, ts.Length - 1), str2);
+ }
+ }
+ finally
+ {
+ Marshal.FreeCoTaskMem(AnsiStr);
+ }
+ }
+ }
+
+ [Fact]
+ public void StringToCoTaskMemUniToString()
+ {
+ foreach (String ts in TestStrings)
+ {
+ if (ts.Contains("\0"))
+ continue; //Skip the string with nulls case
+
+ IntPtr UniStr = Marshal.StringToCoTaskMemUni(ts);
+ try
+ {
+ String str = Marshal.PtrToStringUni(UniStr);
+
+ Assert.Equal(ts, str);
+ if (ts.Length > 0)
+ {
+ String str2 = Marshal.PtrToStringUni(UniStr, ts.Length - 1);
+ Assert.Equal(ts.Substring(0, ts.Length - 1), str2);
+ }
+ }
+ finally
+ {
+ Marshal.FreeCoTaskMem(UniStr);
+ }
+ }
+ }
+
+ [Fact]
+ public void StringToHGlobalAnsiToString()
+ {
+ foreach (String ts in TestStrings)
+ {
+ if (ts.Contains("\0"))
+ continue; //Skip the string with nulls case
+
+ IntPtr AnsiStr = Marshal.StringToHGlobalAnsi(ts);
+ try
+ {
+ String str = Marshal.PtrToStringAnsi(AnsiStr);
+
+ Assert.Equal(ts, str);
+ if (ts.Length > 0)
+ {
+ String str2 = Marshal.PtrToStringAnsi(AnsiStr, ts.Length - 1);
+ Assert.Equal(ts.Substring(0, ts.Length - 1), str2);
+ }
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(AnsiStr);
+ }
+ }
+ }
+
+ [Fact]
+ public void StringToHGlobalUniToString()
+ {
+ foreach (String ts in TestStrings)
+ {
+ if (ts.Contains("\0"))
+ continue; //Skip the string with nulls case
+
+ IntPtr UniStr = Marshal.StringToHGlobalUni(ts);
+ try
+ {
+ String str = Marshal.PtrToStringUni(UniStr);
+
+ Assert.Equal(ts, str);
+ if (ts.Length > 0)
+ {
+ String str2 = Marshal.PtrToStringUni(UniStr, ts.Length - 1);
+ Assert.Equal(ts.Substring(0, ts.Length - 1), str2);
+ }
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(UniStr);
+ }
+ }
+
+ }
+
+#if netcoreapp
+ [Fact]
+ public void TestUTF8String()
+ {
+ foreach (String srcString in TestStrings)
+ {
+ // we assume string null terminated
+ if (srcString.Contains("\0"))
+ continue;
+
+ IntPtr ptrString = Marshal.StringToCoTaskMemUTF8(srcString);
+ try
+ {
+ string retString = Marshal.PtrToStringUTF8(ptrString);
+
+ Assert.Equal(srcString, retString);
+ if (srcString.Length > 0)
+ {
+ string retString2 = Marshal.PtrToStringUTF8(ptrString, srcString.Length - 1);
+ Assert.Equal(srcString.Substring(0, srcString.Length - 1), retString2);
+ }
+ }
+ finally
+ {
+ Marshal.FreeCoTaskMem(ptrString);
+ }
+ }
+ }
+
+ [Fact]
+ public void TestNullString_UTF8()
+ {
+ Assert.Null(Marshal.PtrToStringUTF8(IntPtr.Zero));
+ }
+#endif
+
+ [Fact]
+ public void TestNullString()
+ {
+ Assert.Null(Marshal.PtrToStringUni(IntPtr.Zero));
+ Assert.Null(Marshal.PtrToStringAnsi(IntPtr.Zero));
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+ public class StructureToPtrTests
+ {
+ public struct StructWithIntField
+ {
+ public int value;
+ }
+
+ public struct StructWithByValArray
+ {
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
+ public StructWithIntField[] array;
+ }
+
+ public struct StructWithBoolArray
+ {
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
+ public bool[] array;
+ }
+
+ public struct StructWithDateArray
+ {
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
+ public DateTime[] array;
+ }
+
+ [StructLayout(LayoutKind.Auto)]
+ public struct SomeTestStruct_Auto
+ {
+ public int i;
+ }
+
+ [Fact]
+ public void AutoLayoutStructureTest()
+ {
+ var someTs_Auto = new SomeTestStruct_Auto();
+ ArgumentException ex = AssertExtensions.Throws<ArgumentException>("structure", () => Marshal.StructureToPtr(someTs_Auto, new IntPtr(123), true));
+ }
+
+ [Fact]
+ public void NullParameter()
+ {
+ IntPtr ip = IntPtr.Zero;
+ AssertExtensions.Throws<ArgumentNullException>("ptr", () => Marshal.StructureToPtr<SomeTestStruct_Auto>(new SomeTestStruct_Auto(), ip, true));
+
+ ip = new IntPtr(123);
+ AssertExtensions.Throws<ArgumentNullException>("structure", () => Marshal.StructureToPtr<Object>(null, ip, true));
+ }
+
+ [Fact]
+ public void VerifyByValBoolArray()
+ {
+ var structure1 = new StructWithBoolArray()
+ {
+ array = new bool[]
+ {
+ true,true,true,true
+ }
+ };
+
+ int size = Marshal.SizeOf(structure1);
+ IntPtr memory = Marshal.AllocHGlobal(size + sizeof(Int32));
+
+ try
+ {
+ Marshal.WriteInt32(memory, size, 0xFF);
+ Marshal.StructureToPtr(structure1, memory, false);
+ Marshal.StructureToPtr(structure1, memory, true);
+ Assert.Equal(0xFF, Marshal.ReadInt32(memory, size));
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(memory);
+ }
+ }
+
+ [Fact]
+ public void VerifyByValArrayInStruct()
+ {
+ // equal
+ var structure1 = new StructWithByValArray()
+ {
+ array = new StructWithIntField[]
+ {
+ new StructWithIntField { value = 1 },
+ new StructWithIntField { value = 2 },
+ new StructWithIntField { value = 3 },
+ new StructWithIntField { value = 4 },
+ new StructWithIntField { value = 5 }
+ }
+ };
+ int size = Marshal.SizeOf(structure1);
+ IntPtr memory = Marshal.AllocHGlobal(size);
+ try
+ {
+ Marshal.StructureToPtr(structure1, memory, false);
+ Marshal.StructureToPtr(structure1, memory, true);
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(memory);
+ }
+
+ // underflow
+ var structure2 = new StructWithByValArray()
+ {
+ array = new StructWithIntField[]
+ {
+ new StructWithIntField { value = 1 },
+ new StructWithIntField { value = 2 },
+ new StructWithIntField { value = 3 },
+ new StructWithIntField { value = 4 }
+ }
+ };
+ size = Marshal.SizeOf(structure2);
+ memory = Marshal.AllocHGlobal(size);
+ try
+ {
+ Assert.Throws<ArgumentException>(() => Marshal.StructureToPtr(structure2, memory, false));
+ Assert.Throws<ArgumentException>(() => Marshal.StructureToPtr(structure2, memory, true));
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(memory);
+ }
+
+ // overflow
+ var structure3 = new StructWithByValArray()
+ {
+ array = new StructWithIntField[]
+ {
+ new StructWithIntField { value = 1 },
+ new StructWithIntField { value = 2 },
+ new StructWithIntField { value = 3 },
+ new StructWithIntField { value = 4 },
+ new StructWithIntField { value = 5 },
+ new StructWithIntField { value = 6 }
+ }
+ };
+
+ size = Marshal.SizeOf(structure3);
+ memory = Marshal.AllocHGlobal(size);
+ try
+ {
+ Marshal.StructureToPtr(structure3, memory, false);
+ Marshal.StructureToPtr(structure3, memory, true);
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(memory);
+ }
+ }
+
+ [Fact]
+ public void VerfiyByValDateArray()
+ {
+ var structure1 = new StructWithDateArray()
+ {
+ array = new DateTime[]
+ {
+ DateTime.Now, DateTime.Now , DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now , DateTime.Now, DateTime.Now
+ }
+ };
+
+ int size = Marshal.SizeOf(structure1);
+ IntPtr memory = Marshal.AllocHGlobal(size);
+ try
+ {
+ Marshal.StructureToPtr(structure1, memory, false);
+ Marshal.StructureToPtr(structure1, memory, true);
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(memory);
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+ public class UnsafeAddrOfPinnedArrayElementTests
+ {
+ [Fact]
+ public void NullParameter()
+ {
+ int[] array = null;
+ AssertExtensions.Throws<ArgumentNullException>("arr", () => Marshal.UnsafeAddrOfPinnedArrayElement<int>(array, 0));
+ }
+
+ [Fact]
+ public void PrimitiveType()
+ {
+ int[] array = new int[] { 1, 2, 3 };
+ GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned);
+ try
+ {
+ IntPtr v0 = Marshal.UnsafeAddrOfPinnedArrayElement<int>(array, 0);
+ Assert.Equal(1, Marshal.ReadInt32(v0));
+
+ IntPtr v1 = Marshal.UnsafeAddrOfPinnedArrayElement<int>(array, 1);
+ Assert.Equal(2, Marshal.ReadInt32(v1));
+
+ IntPtr v2 = Marshal.UnsafeAddrOfPinnedArrayElement<int>(array, 2);
+ Assert.Equal(3, Marshal.ReadInt32(v2));
+ }
+ finally
+ {
+ handle.Free();
+ }
+ }
+
+
+ struct Point
+ {
+ public int x;
+ public int y;
+ }
+
+ [Fact]
+ public void StructType()
+ {
+ Point[] array = new Point[]{
+ new Point(){x = 100, y = 100},
+ new Point(){x = -1, y = -1},
+ new Point(){x = 0, y = 0},
+ };
+
+ GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned);
+ try
+ {
+ IntPtr v0 = Marshal.UnsafeAddrOfPinnedArrayElement<Point>(array, 0);
+ Point p0 = Marshal.PtrToStructure<Point>(v0);
+ Assert.Equal(100, p0.x);
+ Assert.Equal(100, p0.y);
+
+ IntPtr v1 = Marshal.UnsafeAddrOfPinnedArrayElement<Point>(array, 1);
+ Point p1 = Marshal.PtrToStructure<Point>(v1);
+ Assert.Equal(-1, p1.x);
+ Assert.Equal(-1, p1.y);
+
+ IntPtr v2 = Marshal.UnsafeAddrOfPinnedArrayElement<Point>(array, 2);
+ Point p2 = Marshal.PtrToStructure<Point>(v2);
+ Assert.Equal(0, p2.x);
+ Assert.Equal(0, p2.y);
+ }
+ finally
+ {
+ handle.Free();
+ }
+ }
+ }
+}