summaryrefslogtreecommitdiff
path: root/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs')
-rw-r--r--src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs68
1 files changed, 55 insertions, 13 deletions
diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs
index 5e9fd31081..5e1396b670 100644
--- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs
+++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs
@@ -4,16 +4,23 @@
using System.Collections.Generic;
using System.Reflection;
-using System.Reflection.Emit;
using System.Security;
using System.Text;
using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;
-using Win32Native = Microsoft.Win32.Win32Native;
+using Microsoft.Win32;
using System.Diagnostics;
using System.Runtime.InteropServices.ComTypes;
using System.StubHelpers;
+using Internal.Runtime.CompilerServices;
+
+#if BIT64
+using nuint = System.UInt64;
+#else
+using nuint = System.UInt32;
+#endif // BIT64
+
namespace System.Runtime.InteropServices
{
/// <summary>
@@ -238,15 +245,25 @@ namespace System.Runtime.InteropServices
/// <summary>
/// IMPORTANT NOTICE: This method does not do any verification on the array.
- /// It must be used with EXTREME CAUTION since passing in an array that is
- /// not pinned or in the fixed heap can cause unexpected results.
+ /// It must be used with EXTREME CAUTION since passing in invalid index or
+ /// an array that is not pinned can cause unexpected results.
/// </summary>
- [MethodImpl(MethodImplOptions.InternalCall)]
- public static extern IntPtr UnsafeAddrOfPinnedArrayElement(Array arr, int index);
+ public static unsafe IntPtr UnsafeAddrOfPinnedArrayElement(Array arr, int index)
+ {
+ if (arr == null)
+ throw new ArgumentNullException(nameof(arr));
- public static IntPtr UnsafeAddrOfPinnedArrayElement<T>(T[] arr, int index)
+ void* pRawData = Unsafe.AsPointer(ref arr.GetRawArrayData());
+ return (IntPtr)((byte*)pRawData + (uint)index * (nuint)arr.GetElementSize());
+ }
+
+ public static unsafe IntPtr UnsafeAddrOfPinnedArrayElement<T>(T[] arr, int index)
{
- return UnsafeAddrOfPinnedArrayElement((Array)arr, index);
+ if (arr == null)
+ throw new ArgumentNullException(nameof(arr));
+
+ void* pRawData = Unsafe.AsPointer(ref arr.GetRawSzArrayData());
+ return (IntPtr)((byte*)pRawData + (uint)index * (nuint)Unsafe.SizeOf<T>());
}
public static void Copy(int[] source, int startIndex, IntPtr destination, int length)
@@ -289,8 +306,17 @@ namespace System.Runtime.InteropServices
CopyToNative(source, startIndex, destination, length);
}
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern void CopyToNative(object source, int startIndex, IntPtr destination, int length);
+ private static unsafe void CopyToNative<T>(T[] source, int startIndex, IntPtr destination, int length)
+ {
+ if (source == null)
+ throw new ArgumentNullException(nameof(source));
+ if (destination == IntPtr.Zero)
+ throw new ArgumentNullException(nameof(destination));
+
+ // The rest of the argument validation is done by CopyTo
+
+ new Span<T>(source, startIndex, length).CopyTo(new Span<T>((void*)destination, length));
+ }
public static void Copy(IntPtr source, int[] destination, int startIndex, int length)
{
@@ -332,9 +358,22 @@ namespace System.Runtime.InteropServices
CopyToManaged(source, destination, startIndex, length);
}
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern void CopyToManaged(IntPtr source, object destination, int startIndex, int length);
-
+ private static unsafe void CopyToManaged<T>(IntPtr source, T[] destination, int startIndex, int length)
+ {
+ if (source == IntPtr.Zero)
+ throw new ArgumentNullException(nameof(source));
+ if (destination == null)
+ throw new ArgumentNullException(nameof(destination));
+ if (startIndex < 0)
+ throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_StartIndex);
+ if (length < 0)
+ throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_NeedNonNegNum);
+
+ // The rest of the argument validation is done by CopyTo
+
+ new Span<T>((void*)source, length).CopyTo(new Span<T>(destination, startIndex, length));
+ }
+
public static byte ReadByte(object ptr, int ofs)
{
return ReadValueSlow(ptr, ofs, (IntPtr nativeHome, int offset) => ReadByte(nativeHome, offset));
@@ -837,6 +876,9 @@ namespace System.Runtime.InteropServices
public static void DestroyStructure<T>(IntPtr ptr) => DestroyStructure(ptr, typeof(T));
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal static extern bool IsPinnable(object obj);
+
#if FEATURE_COMINTEROP
/// <summary>
/// Returns the HInstance for this module. Returns -1 if the module doesn't have