diff options
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.cs | 181 |
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()); |