Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/System.Private.Interop/src/System/Runtime/InteropServices/Marshal.cs')
-rw-r--r--src/System.Private.Interop/src/System/Runtime/InteropServices/Marshal.cs181
1 files changed, 115 insertions, 66 deletions
diff --git a/src/System.Private.Interop/src/System/Runtime/InteropServices/Marshal.cs b/src/System.Private.Interop/src/System/Runtime/InteropServices/Marshal.cs
index d565e199f..31365c9c7 100644
--- a/src/System.Private.Interop/src/System/Runtime/InteropServices/Marshal.cs
+++ b/src/System.Private.Interop/src/System/Runtime/InteropServices/Marshal.cs
@@ -111,6 +111,44 @@ namespace System.Runtime.InteropServices
return PtrToStringUni(ptr);
}
+ public static unsafe String PtrToStringUTF8(IntPtr ptr)
+ {
+ if (IntPtr.Zero == ptr)
+ {
+ return null;
+ }
+ else
+ {
+ int nbBytes = lstrlenA(ptr);
+ return PtrToStringUTF8(ptr, nbBytes);
+ }
+ }
+
+ public static unsafe String PtrToStringUTF8(IntPtr ptr, int byteLen)
+ {
+ if (byteLen < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(byteLen), SR.ArgumentOutOfRange_NeedNonNegNum);
+ }
+ else if (IntPtr.Zero == ptr)
+ {
+ return null;
+ }
+ else if (IsWin32Atom(ptr))
+ {
+ return null;
+ }
+ else if (byteLen == 0)
+ {
+ return string.Empty;
+ }
+ else
+ {
+ byte* pByte = (byte*)ptr.ToPointer();
+ return Encoding.UTF8.GetString(pByte, byteLen);
+ }
+ }
+
//====================================================================
// SizeOf()
//====================================================================
@@ -125,16 +163,16 @@ namespace System.Runtime.InteropServices
public static int SizeOf<T>(T structure)
{
- return SizeOf<T>();
+ return SizeOf((object)structure);
}
- public static int SizeOf(Object structure)
+ public static int SizeOf(object structure)
{
if (structure == null)
throw new ArgumentNullException(nameof(structure));
// we never had a check for generics here
- return SizeOfHelper(structure.GetType(), true);
+ return SizeOfHelper(structure.GetType());
}
public static int SizeOf(Type t)
@@ -144,27 +182,27 @@ namespace System.Runtime.InteropServices
if (t.TypeHandle.IsGenericType() || t.TypeHandle.IsGenericTypeDefinition())
throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(t));
- return SizeOfHelper(t, true);
+ return SizeOfHelper(t);
}
- private static int SizeOfHelper(Type t, bool throwIfNotMarshalable)
+ private static int SizeOfHelper(Type t)
{
RuntimeTypeHandle typeHandle = t.TypeHandle;
- int size;
- if (RuntimeInteropData.Instance.TryGetStructUnsafeStructSize(typeHandle, out size))
+ if (RuntimeInteropData.Instance.TryGetStructUnsafeStructSize(typeHandle, out int size))
{
return size;
}
- if (!typeHandle.IsBlittable() && !typeHandle.IsValueType())
- {
- throw new MissingInteropDataException(SR.StructMarshalling_MissingInteropData, t);
- }
- else
+ // IsBlittable() checks whether the type contains GC references. It is approximate check with false positives.
+ // This fallback path will return incorrect answer for types that do not contain GC references, but that are
+ // not actually blittable; e.g. for types with bool fields.
+ if (typeHandle.IsBlittable() && typeHandle.IsValueType())
{
return typeHandle.GetValueTypeSize();
}
+
+ throw new MissingInteropDataException(SR.StructMarshalling_MissingInteropData, t);
}
//====================================================================
@@ -181,15 +219,7 @@ namespace System.Runtime.InteropServices
if (t.TypeHandle.IsGenericType() || t.TypeHandle.IsGenericTypeDefinition())
throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(t));
-
- return OffsetOfHelper(t, fieldName);
- }
-
- private static IntPtr OffsetOfHelper(Type t, String fieldName)
- {
- bool structExists;
- uint offset;
- if (RuntimeInteropData.Instance.TryGetStructFieldOffset(t.TypeHandle, fieldName, out structExists, out offset))
+ if (RuntimeInteropData.Instance.TryGetStructFieldOffset(t.TypeHandle, fieldName, out bool structExists, out uint offset))
{
return new IntPtr(offset);
}
@@ -199,10 +229,8 @@ namespace System.Runtime.InteropServices
{
throw new ArgumentException(SR.Format(SR.Argument_OffsetOfFieldNotFound, t.TypeHandle.GetDisplayName()), nameof(fieldName));
}
- else
- {
- throw new MissingInteropDataException(SR.StructMarshalling_MissingInteropData, t);
- }
+
+ throw new MissingInteropDataException(SR.StructMarshalling_MissingInteropData, t);
}
public static IntPtr OffsetOf<T>(String fieldName)
@@ -813,6 +841,35 @@ namespace System.Runtime.InteropServices
}
}
+ public static unsafe IntPtr StringToCoTaskMemUTF8(String s)
+ {
+ if (s == null)
+ {
+ return IntPtr.Zero;
+ }
+ else
+ {
+ int nb = Encoding.UTF8.GetMaxByteCount(s.Length);
+
+ IntPtr pMem = PInvokeMarshal.CoTaskMemAlloc(new UIntPtr((uint)nb + 1));
+
+ if (pMem == IntPtr.Zero)
+ {
+ throw new OutOfMemoryException();
+ }
+ else
+ {
+ fixed (char* firstChar = s)
+ {
+ byte* pbMem = (byte*)pMem;
+ int nbWritten = Encoding.UTF8.GetBytes(firstChar, s.Length, pbMem, nb);
+ pbMem[nbWritten] = 0;
+ }
+ return pMem;
+ }
+ }
+ }
+
public static unsafe IntPtr StringToCoTaskMemAnsi(String s)
{
if (s == null)
@@ -945,7 +1002,7 @@ namespace System.Runtime.InteropServices
{
if (IsNotWin32Atom(ptr))
{
- ExternalInterop.SysFreeString(ptr);
+ McgMarshal.SysFreeString(ptr);
}
}
@@ -991,6 +1048,12 @@ namespace System.Runtime.InteropServices
FreeCoTaskMem(s);
}
+ public static unsafe void ZeroFreeCoTaskMemUTF8(IntPtr s)
+ {
+ SecureZeroMemory(s, lstrlenA(s));
+ FreeCoTaskMem(s);
+ }
+
public static void ZeroFreeGlobalAllocAnsi(IntPtr s)
{
SecureZeroMemory(s, lstrlenA(s));
@@ -1029,8 +1092,27 @@ namespace System.Runtime.InteropServices
// Boxed struct start at offset 1 (EEType* at offset 0) while class start at offset 0
int offset = structureTypeHandle.IsValueType() ? 1 : 0;
+ bool useMemCpy = false;
+
+ if (RuntimeInteropData.Instance.TryGetStructUnmarshalStub(structureTypeHandle, out IntPtr unmarshalStub))
+ {
+ if (unmarshalStub != IntPtr.Zero)
+ {
+ InteropExtensions.PinObjectAndCall(structure,
+ unboxedStructPtr =>
+ {
+ CalliIntrinsics.Call<int>(
+ unmarshalStub,
+ (void*)ptr, // unsafe (no need to adjust as it is always struct)
+ ((void*)((IntPtr*)unboxedStructPtr + offset)) // safe (need to adjust offset as it could be class)
+ );
+ });
+ return;
+ }
+ useMemCpy = true;
+ }
- if (structureTypeHandle.IsBlittable() && structureTypeHandle.IsValueType())
+ if (useMemCpy || structureTypeHandle.IsBlittable())
{
int structSize = Marshal.SizeOf(structure);
InteropExtensions.PinObjectAndCall(structure,
@@ -1045,21 +1127,6 @@ namespace System.Runtime.InteropServices
return;
}
- IntPtr unmarshalStub;
- if (RuntimeInteropData.Instance.TryGetStructUnmarshalStub(structureTypeHandle, out unmarshalStub))
- {
- InteropExtensions.PinObjectAndCall(structure,
- unboxedStructPtr =>
- {
- CalliIntrinsics.Call<int>(
- unmarshalStub,
- (void*)ptr, // unsafe (no need to adjust as it is always struct)
- ((void*)((IntPtr*)unboxedStructPtr + offset)) // safe (need to adjust offset as it could be class)
- );
- });
- return;
- }
-
throw new MissingInteropDataException(SR.StructMarshalling_MissingInteropData, structure.GetType());
}
@@ -1067,12 +1134,8 @@ namespace System.Runtime.InteropServices
// Creates a new instance of "structuretype" and marshals data from a
// native memory block to it.
//====================================================================
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
public static Object PtrToStructure(IntPtr ptr, Type structureType)
{
- // Boxing the struct here is important to ensure that the original copy is written to,
- // not the autoboxed copy
-
if (ptr == IntPtr.Zero)
throw new ArgumentNullException(nameof(ptr));
@@ -1138,10 +1201,9 @@ namespace System.Runtime.InteropServices
// Boxed struct start at offset 1 (EEType* at offset 0) while class start at offset 0
int offset = structureTypeHandle.IsValueType() ? 1 : 0;
+ bool useMemCpy = false;
- bool isBlittable = false; // whether Mcg treat this struct as blittable struct
- IntPtr marshalStub;
- if (RuntimeInteropData.Instance.TryGetStructMarshalStub(structureTypeHandle, out marshalStub))
+ if (RuntimeInteropData.Instance.TryGetStructMarshalStub(structureTypeHandle, out IntPtr marshalStub))
{
if (marshalStub != IntPtr.Zero)
{
@@ -1156,13 +1218,10 @@ namespace System.Runtime.InteropServices
});
return;
}
- else
- {
- isBlittable = true;
- }
+ useMemCpy = true;
}
- if (isBlittable || structureTypeHandle.IsBlittable()) // blittable
+ if (useMemCpy || structureTypeHandle.IsBlittable())
{
int structSize = Marshal.SizeOf(structure);
InteropExtensions.PinObjectAndCall(structure,
@@ -1189,7 +1248,7 @@ namespace System.Runtime.InteropServices
// DestroyStructure()
//
//====================================================================
- public static void DestroyStructure(IntPtr ptr, Type structuretype)
+ public static unsafe void DestroyStructure(IntPtr ptr, Type structuretype)
{
if (ptr == IntPtr.Zero)
throw new ArgumentNullException(nameof(ptr));
@@ -1209,14 +1268,6 @@ namespace System.Runtime.InteropServices
throw new ArgumentException(SR.Argument_MustHaveLayoutOrBeBlittable, structureTypeHandle.GetDisplayName());
}
-
- DestroyStructureHelper(ptr, structuretype);
- }
-
- private static unsafe void DestroyStructureHelper(IntPtr ptr, Type structuretype)
- {
- RuntimeTypeHandle structureTypeHandle = structuretype.TypeHandle;
-
// Boxed struct start at offset 1 (EEType* at offset 0) while class start at offset 0
int offset = structureTypeHandle.IsValueType() ? 1 : 0;
@@ -1226,9 +1277,7 @@ namespace System.Runtime.InteropServices
return;
}
- IntPtr destroyStructureStub;
- bool hasInvalidLayout;
- if (RuntimeInteropData.Instance.TryGetDestroyStructureStub(structureTypeHandle, out destroyStructureStub, out hasInvalidLayout))
+ if (RuntimeInteropData.Instance.TryGetDestroyStructureStub(structureTypeHandle, out IntPtr destroyStructureStub, out bool hasInvalidLayout))
{
if (hasInvalidLayout)
throw new ArgumentException(SR.Argument_MustHaveLayoutOrBeBlittable, structureTypeHandle.GetDisplayName());