From 63e6229784a2ef5de4f8ed6b6d402408a1be5615 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 29 Jun 2022 17:01:10 -0700 Subject: [PATCH 1/4] Update all internal marshallers that don't require pinning support to the new model --- .../Common/src/Interop/Interop.Ldap.cs | 68 +++---- .../Advapi32/Interop.LsaLookupNames2.cs | 31 ++-- .../Windows/WebSocket/Interop.Structs.cs | 36 ++-- .../InteropServices/HandleRefMarshaller.cs | 21 ++- .../Diagnostics/Reader/UnsafeNativeMethods.cs | 102 +++++----- .../src/System/Drawing/GdiplusNative.cs | 2 +- .../src/System/Drawing/Graphics.cs | 86 +++++---- .../src/System/Drawing/Image.cs | 45 ++--- .../Drawing/Imaging/MetafileHeaderWmf.cs | 174 +++++++++--------- 9 files changed, 305 insertions(+), 260 deletions(-) diff --git a/src/libraries/Common/src/Interop/Interop.Ldap.cs b/src/libraries/Common/src/Interop/Interop.Ldap.cs index cc830f8da215d..040a8b66818de 100644 --- a/src/libraries/Common/src/Interop/Interop.Ldap.cs +++ b/src/libraries/Common/src/Interop/Interop.Ldap.cs @@ -222,48 +222,52 @@ internal struct LdapReferralCallback public NOTIFYOFNEWCONNECTIONInternal notify; public DEREFERENCECONNECTIONInternal dereference; #if NET7_0_OR_GREATER - public static readonly unsafe int Size = sizeof(Marshaller.Native); + public static readonly unsafe int Size = sizeof(Marshaller.MarshalValue.Native); - [CustomTypeMarshaller(typeof(LdapReferralCallback), Features = CustomTypeMarshallerFeatures.UnmanagedResources | CustomTypeMarshallerFeatures.TwoStageMarshalling)] - public unsafe struct Marshaller + [CustomMarshaller(typeof(LdapReferralCallback), Scenario.ManagedToUnmanagedIn, typeof(MarshalValue))] + [CustomMarshaller(typeof(LdapReferralCallback), Scenario.ManagedToUnmanagedRef, typeof(MarshalValue))] + [CustomMarshaller(typeof(LdapReferralCallback), Scenario.ManagedToUnmanagedOut, typeof(MarshalValue))] + public static class Marshaller { - public unsafe struct Native + public unsafe struct MarshalValue { - public int sizeofcallback; - public IntPtr query; - public IntPtr notify; - public IntPtr dereference; - } + public unsafe struct Native + { + public int sizeofcallback; + public IntPtr query; + public IntPtr notify; + public IntPtr dereference; + } - private LdapReferralCallback _managed; - private Native _native; + private LdapReferralCallback _managed; + private Native _native; - public Marshaller(LdapReferralCallback managed) - : this() - { - _managed = managed; - _native.sizeofcallback = sizeof(Native); - _native.query = managed.query is not null ? Marshal.GetFunctionPointerForDelegate(managed.query) : IntPtr.Zero; - _native.notify = managed.notify is not null ? Marshal.GetFunctionPointerForDelegate(managed.notify) : IntPtr.Zero; - _native.dereference = managed.dereference is not null ? Marshal.GetFunctionPointerForDelegate(managed.dereference) : IntPtr.Zero; - } + public void FromManaged(LdapReferralCallback managed) + { + _managed = managed; + _native.sizeofcallback = sizeof(Native); + _native.query = managed.query is not null ? Marshal.GetFunctionPointerForDelegate(managed.query) : IntPtr.Zero; + _native.notify = managed.notify is not null ? Marshal.GetFunctionPointerForDelegate(managed.notify) : IntPtr.Zero; + _native.dereference = managed.dereference is not null ? Marshal.GetFunctionPointerForDelegate(managed.dereference) : IntPtr.Zero; + } - public Native ToNativeValue() => _native; + public Native ToUnmanaged() => _native; - public void FromNativeValue(Native value) => _native = value; + public void FromUnmanaged(Native value) => _native = value; - public LdapReferralCallback ToManaged() - { - return new LdapReferralCallback() + public LdapReferralCallback ToManaged() { - sizeofcallback = _native.sizeofcallback, - query = _native.query != IntPtr.Zero ? Marshal.GetDelegateForFunctionPointer(_native.query) : null, - notify = _native.notify != IntPtr.Zero ? Marshal.GetDelegateForFunctionPointer(_native.notify) : null, - dereference = _native.dereference != IntPtr.Zero ? Marshal.GetDelegateForFunctionPointer(_native.dereference) : null - }; + return new LdapReferralCallback() + { + sizeofcallback = _native.sizeofcallback, + query = _native.query != IntPtr.Zero ? Marshal.GetDelegateForFunctionPointer(_native.query) : null, + notify = _native.notify != IntPtr.Zero ? Marshal.GetDelegateForFunctionPointer(_native.notify) : null, + dereference = _native.dereference != IntPtr.Zero ? Marshal.GetDelegateForFunctionPointer(_native.dereference) : null + }; + } + + public void NotifyInvokeSucceeded() => GC.KeepAlive(_managed); } - - public void FreeNative() => GC.KeepAlive(_managed); } #else public static readonly unsafe int Size = Marshal.SizeOf(); diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.LsaLookupNames2.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.LsaLookupNames2.cs index 6a59a1061642d..e0f4c9f37d0de 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.LsaLookupNames2.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.LsaLookupNames2.cs @@ -20,28 +20,37 @@ internal static partial uint LsaLookupNames2( out SafeLsaMemoryHandle sids ); - [NativeMarshalling(typeof(Native))] + [NativeMarshalling(typeof(Marshaller))] internal struct MARSHALLED_UNICODE_STRING { internal ushort Length; internal ushort MaximumLength; internal string Buffer; - [CustomTypeMarshaller(typeof(MARSHALLED_UNICODE_STRING), Direction = CustomTypeMarshallerDirection.In, Features = CustomTypeMarshallerFeatures.UnmanagedResources)] - public struct Native + [CustomMarshaller(typeof(MARSHALLED_UNICODE_STRING), Scenario.ManagedToUnmanagedIn, typeof(Marshaller))] + [CustomMarshaller(typeof(MARSHALLED_UNICODE_STRING), Scenario.ElementIn, typeof(Marshaller))] + public static class Marshaller { - internal ushort Length; - internal ushort MaximumLength; - internal IntPtr Buffer; + public static Native ConvertToUnmanaged(MARSHALLED_UNICODE_STRING managed) + { + Native n; + n.Length = managed.Length; + n.MaximumLength = managed.MaximumLength; + n.Buffer = Marshal.StringToCoTaskMemUni(managed.Buffer); + return n; + } - public Native(MARSHALLED_UNICODE_STRING managed) + public static void Free(Native native) { - Length = managed.Length; - MaximumLength = managed.MaximumLength; - Buffer = Marshal.StringToCoTaskMemUni(managed.Buffer); + Marshal.FreeCoTaskMem(native.Buffer); } - public void FreeNative() => Marshal.FreeCoTaskMem(Buffer); + public struct Native + { + internal ushort Length; + internal ushort MaximumLength; + internal IntPtr Buffer; + } } } } diff --git a/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.Structs.cs b/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.Structs.cs index 269ef4659c05b..59cf02a950de3 100644 --- a/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.Structs.cs +++ b/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.Structs.cs @@ -42,7 +42,7 @@ internal struct CloseBuffer internal ushort CloseStatus; } - [NativeMarshalling(typeof(Native))] + [NativeMarshalling(typeof(Marshaller))] internal struct HttpHeader { internal string Name; @@ -50,26 +50,32 @@ internal struct HttpHeader internal string Value; internal uint ValueLength; - [CustomTypeMarshaller(typeof(HttpHeader), Direction = CustomTypeMarshallerDirection.In, Features = CustomTypeMarshallerFeatures.UnmanagedResources)] - internal struct Native + [CustomMarshaller(typeof(HttpHeader), Scenario.ManagedToUnmanagedIn, typeof(Marshaller))] + [CustomMarshaller(typeof(HttpHeader), Scenario.ElementIn, typeof(Marshaller))] + public static class Marshaller { - private IntPtr Name; - private uint NameLength; - private IntPtr Value; - private uint ValueLength; + public static Native ConvertToUnmanaged(HttpHeader managed) + { + Native n; + n.Name = Marshal.StringToCoTaskMemAnsi(managed.Name); + n.NameLength = managed.NameLength; + n.Value = Marshal.StringToCoTaskMemAnsi(managed.Value); + n.ValueLength = managed.ValueLength; + return n; + } - public Native(HttpHeader managed) + public static void Free(Native n) { - Name = Marshal.StringToCoTaskMemAnsi(managed.Name); - NameLength = managed.NameLength; - Value = Marshal.StringToCoTaskMemAnsi(managed.Value); - ValueLength = managed.ValueLength; + Marshal.FreeCoTaskMem(n.Name); + Marshal.FreeCoTaskMem(n.Value); } - public void FreeNative() + internal struct Native { - Marshal.FreeCoTaskMem(Name); - Marshal.FreeCoTaskMem(Value); + public IntPtr Name; + public uint NameLength; + public IntPtr Value; + public uint ValueLength; } } } diff --git a/src/libraries/Common/src/System/Runtime/InteropServices/HandleRefMarshaller.cs b/src/libraries/Common/src/System/Runtime/InteropServices/HandleRefMarshaller.cs index f414803d67b2f..6ec2f42d71927 100644 --- a/src/libraries/Common/src/System/Runtime/InteropServices/HandleRefMarshaller.cs +++ b/src/libraries/Common/src/System/Runtime/InteropServices/HandleRefMarshaller.cs @@ -5,18 +5,21 @@ namespace System.Runtime.InteropServices.Marshalling { - [CustomTypeMarshaller(typeof(HandleRef), Direction = CustomTypeMarshallerDirection.In, Features = CustomTypeMarshallerFeatures.UnmanagedResources | CustomTypeMarshallerFeatures.TwoStageMarshalling)] - internal struct HandleRefMarshaller + [CustomMarshaller(typeof(HandleRef), Scenario.ManagedToUnmanagedIn, typeof(KeepAliveMarshaller))] + internal static class HandleRefMarshaller { - private HandleRef _handle; - - public HandleRefMarshaller(HandleRef handle) + internal struct KeepAliveMarshaller { - _handle = handle; - } + private HandleRef _handle; - public IntPtr ToNativeValue() => _handle.Handle; + public void FromManaged(HandleRef handle) + { + _handle = handle; + } - public void FreeNative() => GC.KeepAlive(_handle.Wrapper); + public IntPtr ToUnmanaged() => _handle.Handle; + + public void NotifyInvokeSucceeded() => GC.KeepAlive(_handle.Wrapper); + } } } diff --git a/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/UnsafeNativeMethods.cs b/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/UnsafeNativeMethods.cs index 49015a133a3d3..d7a80e087c7df 100644 --- a/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/UnsafeNativeMethods.cs +++ b/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/UnsafeNativeMethods.cs @@ -356,66 +356,72 @@ internal struct EvtRpcLogin public CoTaskMemUnicodeSafeHandle Password; public int Flags; #if NET7_0_OR_GREATER - [CustomTypeMarshaller(typeof(EvtRpcLogin), Features = CustomTypeMarshallerFeatures.UnmanagedResources | CustomTypeMarshallerFeatures.TwoStageMarshalling)] - public struct Marshaller + [CustomMarshaller(typeof(EvtRpcLogin), Scenario.ManagedToUnmanagedRef, typeof(ValueMarshaller))] + public static class Marshaller { - public struct Native + public struct ValueMarshaller { - public IntPtr Server; - public IntPtr User; - public IntPtr Domain; - public IntPtr Password; - public int Flags; - } + public struct Native + { + public IntPtr Server; + public IntPtr User; + public IntPtr Domain; + public IntPtr Password; + public int Flags; + } - private CoTaskMemUnicodeSafeHandle _passwordHandle; - private Native _value; - private bool _passwordHandleAddRefd; + private CoTaskMemUnicodeSafeHandle _passwordHandle; + private IntPtr _originalHandleValue; + private Native _value; + private bool _passwordHandleAddRefd; - public Marshaller(EvtRpcLogin managed) - { - _passwordHandleAddRefd = false; - _value.Server = Marshal.StringToCoTaskMemUni(managed.Server); - _value.User = Marshal.StringToCoTaskMemUni(managed.User); - _value.Domain = Marshal.StringToCoTaskMemUni(managed.Domain); - _passwordHandle = managed.Password; - _passwordHandle.DangerousAddRef(ref _passwordHandleAddRefd); - _value.Password = _passwordHandle.DangerousGetHandle(); - _value.Flags = managed.Flags; - } + public void FromManaged(EvtRpcLogin managed) + { + _passwordHandleAddRefd = false; + _value.Server = Marshal.StringToCoTaskMemUni(managed.Server); + _value.User = Marshal.StringToCoTaskMemUni(managed.User); + _value.Domain = Marshal.StringToCoTaskMemUni(managed.Domain); + _passwordHandle = managed.Password; + _passwordHandle.DangerousAddRef(ref _passwordHandleAddRefd); + _value.Password = _originalHandleValue = _passwordHandle.DangerousGetHandle(); + _value.Flags = managed.Flags; + } - public Native ToNativeValue() => _value; + public Native ToUnmanaged() => _value; - public void FromNativeValue(Native value) - { - // SafeHandle fields cannot change the underlying handle value during marshalling. - if (_value.Password != value.Password) + public void FromUnmanaged(Native value) { - throw new InvalidOperationException(); + _value = value; } - _value = value; - } - public EvtRpcLogin ToManaged() - { - return new EvtRpcLogin + public EvtRpcLogin ToManaged() { - Server = Marshal.PtrToStringUni(_value.Server), - User = Marshal.PtrToStringUni(_value.User), - Domain = Marshal.PtrToStringUni(_value.Domain), - Password = _passwordHandle, - Flags = _value.Flags - }; - } + // SafeHandle fields cannot change the underlying handle value during marshalling. + if (_value.Password != _originalHandleValue) + { + // Match the same exception type that the built-in marshalling throws. + throw new NotSupportedException(); + } - public void FreeNative() - { - Marshal.FreeCoTaskMem(_value.Server); - Marshal.FreeCoTaskMem(_value.User); - Marshal.FreeCoTaskMem(_value.Domain); - if (_passwordHandleAddRefd) + return new EvtRpcLogin + { + Server = Marshal.PtrToStringUni(_value.Server), + User = Marshal.PtrToStringUni(_value.User), + Domain = Marshal.PtrToStringUni(_value.Domain), + Password = _passwordHandle, + Flags = _value.Flags + }; + } + + public void Free() { - _passwordHandle.DangerousRelease(); + Marshal.FreeCoTaskMem(_value.Server); + Marshal.FreeCoTaskMem(_value.User); + Marshal.FreeCoTaskMem(_value.Domain); + if (_passwordHandleAddRefd) + { + _passwordHandle.DangerousRelease(); + } } } } diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.cs index 0b43bd7686993..709c63d2d7ec7 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.cs @@ -4384,7 +4384,7 @@ private static partial int GdipGetMetafileHeaderFromWmf_Internal(IntPtr hMetafil #endif WmfPlaceableFileHeader wmfplaceable, #if NET7_0_OR_GREATER - [MarshalUsing(typeof(MetafileHeaderWmf.InPlaceMarshaller))] + [MarshalUsing(typeof(MetafileHeaderWmf.Marshaller))] ref MetafileHeaderWmf metafileHeaderWmf #else MetafileHeaderWmf metafileHeaderWmf diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Graphics.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Graphics.cs index a96aaa03e1026..6c19a7566d287 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Graphics.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Graphics.cs @@ -64,26 +64,29 @@ internal static string GetAllocationStack() { public delegate bool DrawImageAbort(IntPtr callbackdata); #if NET7_0_OR_GREATER - [CustomTypeMarshaller(typeof(DrawImageAbort), CustomTypeMarshallerKind.Value, Direction = CustomTypeMarshallerDirection.In, Features = CustomTypeMarshallerFeatures.TwoStageMarshalling | CustomTypeMarshallerFeatures.UnmanagedResources)] - internal unsafe struct DrawImageAbortMarshaller + [CustomMarshaller(typeof(DrawImageAbort), Scenario.ManagedToUnmanagedIn, typeof(KeepAliveMarshaller))] + internal static class DrawImageAbortMarshaller { - private delegate Interop.BOOL DrawImageAbortNative(IntPtr callbackdata); - private DrawImageAbortNative? _managed; - private delegate* unmanaged _nativeFunction; - public DrawImageAbortMarshaller(DrawImageAbort? managed) + internal unsafe struct KeepAliveMarshaller { - _managed = managed is null ? null : data => managed(data) ? Interop.BOOL.TRUE : Interop.BOOL.FALSE; - _nativeFunction = _managed is null ? null : (delegate* unmanaged)Marshal.GetFunctionPointerForDelegate(_managed); - } + private delegate Interop.BOOL DrawImageAbortNative(IntPtr callbackdata); + private DrawImageAbortNative? _managed; + private delegate* unmanaged _nativeFunction; + public void FromManaged(DrawImageAbort? managed) + { + _managed = managed is null ? null : data => managed(data) ? Interop.BOOL.TRUE : Interop.BOOL.FALSE; + _nativeFunction = _managed is null ? null : (delegate* unmanaged)Marshal.GetFunctionPointerForDelegate(_managed); + } - public delegate* unmanaged ToNativeValue() - { - return _nativeFunction; - } + public delegate* unmanaged ToUnmanaged() + { + return _nativeFunction; + } - public void FreeNative() - { - GC.KeepAlive(_managed); + public void NotifyInvokeSucceeded() + { + GC.KeepAlive(_managed); + } } } #endif @@ -106,32 +109,35 @@ public delegate bool EnumerateMetafileProc( PlayRecordCallback? callbackData); #if NET7_0_OR_GREATER - [CustomTypeMarshaller(typeof(EnumerateMetafileProc), CustomTypeMarshallerKind.Value, Direction = CustomTypeMarshallerDirection.In, Features = CustomTypeMarshallerFeatures.TwoStageMarshalling | CustomTypeMarshallerFeatures.UnmanagedResources)] - internal unsafe struct EnumerateMetafileProcMarshaller - { - private delegate Interop.BOOL EnumerateMetafileProcNative( - EmfPlusRecordType recordType, - int flags, - int dataSize, - IntPtr data, - IntPtr callbackData); - private EnumerateMetafileProcNative? _managed; - private delegate* unmanaged _nativeFunction; - public EnumerateMetafileProcMarshaller(EnumerateMetafileProc? managed) - { - _managed = managed is null ? null : (recordType, flags, dataSize, data, callbackData) => - managed(recordType, flags, dataSize, data, callbackData == IntPtr.Zero ? null : Marshal.GetDelegateForFunctionPointer(callbackData)) ? Interop.BOOL.TRUE : Interop.BOOL.FALSE; - _nativeFunction = _managed is null ? null : (delegate* unmanaged)Marshal.GetFunctionPointerForDelegate(_managed); - } + [CustomMarshaller(typeof(EnumerateMetafileProc), Scenario.ManagedToUnmanagedIn, typeof(KeepAliveMarshaller))] + internal static class EnumerateMetafileProcMarshaller + { + internal unsafe struct KeepAliveMarshaller + { + private delegate Interop.BOOL EnumerateMetafileProcNative( + EmfPlusRecordType recordType, + int flags, + int dataSize, + IntPtr data, + IntPtr callbackData); + private EnumerateMetafileProcNative? _managed; + private delegate* unmanaged _nativeFunction; + public void FromManaged(EnumerateMetafileProc? managed) + { + _managed = managed is null ? null : (recordType, flags, dataSize, data, callbackData) => + managed(recordType, flags, dataSize, data, callbackData == IntPtr.Zero ? null : Marshal.GetDelegateForFunctionPointer(callbackData)) ? Interop.BOOL.TRUE : Interop.BOOL.FALSE; + _nativeFunction = _managed is null ? null : (delegate* unmanaged)Marshal.GetFunctionPointerForDelegate(_managed); + } - public delegate* unmanaged ToNativeValue() - { - return _nativeFunction; - } + public delegate* unmanaged ToUnmanaged() + { + return _nativeFunction; + } - public void FreeNative() - { - GC.KeepAlive(_managed); + public void NotifyInvokeSucceeded() + { + GC.KeepAlive(_managed); + } } } #endif diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Image.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Image.cs index 129c9bf40ef24..8170bedf4a183 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Image.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Image.cs @@ -44,34 +44,37 @@ public abstract class Image : MarshalByRefObject, IDisposable, ICloneable, ISeri public delegate bool GetThumbnailImageAbort(); #if NET7_0_OR_GREATER - [CustomTypeMarshaller(typeof(GetThumbnailImageAbort), CustomTypeMarshallerKind.Value, Direction = CustomTypeMarshallerDirection.In, Features = CustomTypeMarshallerFeatures.TwoStageMarshalling | CustomTypeMarshallerFeatures.UnmanagedResources)] - internal unsafe struct GetThumbnailImageAbortMarshaller + [CustomMarshaller(typeof(GetThumbnailImageAbort), Scenario.ManagedToUnmanagedIn, typeof(KeepAliveMarshaller))] + internal static class GetThumbnailImageAbortMarshaller { - private delegate Interop.BOOL GetThumbnailImageAbortNative(IntPtr callbackdata); - private GetThumbnailImageAbortNative? _managed; - private delegate* unmanaged _nativeFunction; - public GetThumbnailImageAbortMarshaller(GetThumbnailImageAbort managed) + internal unsafe struct KeepAliveMarshaller { - if (managed is null) + private delegate Interop.BOOL GetThumbnailImageAbortNative(IntPtr callbackdata); + private GetThumbnailImageAbortNative? _managed; + private delegate* unmanaged _nativeFunction; + public void FromManaged(GetThumbnailImageAbort managed) { - _managed = null; - _nativeFunction = null; + if (managed is null) + { + _managed = null; + _nativeFunction = null; + } + else + { + _managed = data => managed() ? Interop.BOOL.TRUE : Interop.BOOL.FALSE; + _nativeFunction = (delegate* unmanaged)Marshal.GetFunctionPointerForDelegate(_managed); + } } - else + + public delegate* unmanaged ToUnmanaged() { - _managed = data => managed() ? Interop.BOOL.TRUE : Interop.BOOL.FALSE; - _nativeFunction = (delegate* unmanaged)Marshal.GetFunctionPointerForDelegate(_managed); + return _nativeFunction; } - } - public delegate* unmanaged ToNativeValue() - { - return _nativeFunction; - } - - public void FreeNative() - { - GC.KeepAlive(_managed); + public void NotifyInvokeSucceeded() + { + GC.KeepAlive(_managed); + } } } #endif diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/MetafileHeaderWmf.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/MetafileHeaderWmf.cs index 6d52ce69e15be..a700f949bba1e 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/MetafileHeaderWmf.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/MetafileHeaderWmf.cs @@ -58,97 +58,105 @@ internal sealed class MetafileHeaderWmf public int LogicalDpiY; #if NET7_0_OR_GREATER - [CustomTypeMarshaller(typeof(MetafileHeaderWmf), Features = CustomTypeMarshallerFeatures.TwoStageMarshalling)] - internal unsafe struct InPlaceMarshaller + [CustomMarshaller(typeof(MetafileHeaderWmf), Scenario.ManagedToUnmanagedRef, typeof(InPlaceMarshaller))] + internal static class Marshaller { - [StructLayout(LayoutKind.Sequential, Pack = 8)] - internal struct Native + internal unsafe struct InPlaceMarshaller { - /// The ENHMETAHEADER structure is defined natively as a union with WmfHeader. - /// Extreme care should be taken if changing the layout of the corresponding managed - /// structures to minimize the risk of buffer overruns. The affected managed classes - /// are the following: ENHMETAHEADER, MetaHeader, MetafileHeaderWmf, MetafileHeaderEmf. - internal MetafileType type; - internal int size; - internal int version; - internal EmfPlusFlags emfPlusFlags; - internal float dpiX; - internal float dpiY; - internal int X; - internal int Y; - internal int Width; - internal int Height; - internal WmfMetaHeader WmfHeader; - internal int dummy1; - internal int dummy2; - internal int dummy3; - internal int dummy4; - internal int dummy5; - internal int dummy6; - internal int dummy7; - internal int dummy8; - internal int dummy9; - internal int dummy10; - internal int dummy11; - internal int dummy12; - internal int dummy13; - internal int dummy14; - internal int dummy15; - internal int dummy16; - internal int EmfPlusHeaderSize; - internal int LogicalDpiX; - internal int LogicalDpiY; - } + [StructLayout(LayoutKind.Sequential, Pack = 8)] + internal struct Native + { + /// The ENHMETAHEADER structure is defined natively as a union with WmfHeader. + /// Extreme care should be taken if changing the layout of the corresponding managed + /// structures to minimize the risk of buffer overruns. The affected managed classes + /// are the following: ENHMETAHEADER, MetaHeader, MetafileHeaderWmf, MetafileHeaderEmf. + internal MetafileType type; + internal int size; + internal int version; + internal EmfPlusFlags emfPlusFlags; + internal float dpiX; + internal float dpiY; + internal int X; + internal int Y; + internal int Width; + internal int Height; + internal WmfMetaHeader WmfHeader; + internal int dummy1; + internal int dummy2; + internal int dummy3; + internal int dummy4; + internal int dummy5; + internal int dummy6; + internal int dummy7; + internal int dummy8; + internal int dummy9; + internal int dummy10; + internal int dummy11; + internal int dummy12; + internal int dummy13; + internal int dummy14; + internal int dummy15; + internal int dummy16; + internal int EmfPlusHeaderSize; + internal int LogicalDpiX; + internal int LogicalDpiY; + } - private MetafileHeaderWmf _managed; - private Native _native; + private MetafileHeaderWmf? _managed; + private Native _native; - public InPlaceMarshaller(MetafileHeaderWmf managed) - { - _managed = managed; - Unsafe.SkipInit(out _native); - _native.type = managed.type; - _native.size = managed.size; - _native.version = managed.version; - _native.emfPlusFlags = managed.emfPlusFlags; - _native.dpiX = managed.dpiX; - _native.dpiY = managed.dpiY; - _native.X = managed.X; - _native.Y = managed.Y; - _native.Width = managed.Width; - _native.Height = managed.Height; - _native.WmfHeader = managed.WmfHeader.GetNativeValue(); - _native.dummy16 = managed.dummy16; - _native.EmfPlusHeaderSize = managed.EmfPlusHeaderSize; - _native.LogicalDpiX = managed.LogicalDpiX; - _native.LogicalDpiY = managed.LogicalDpiY; - } + public InPlaceMarshaller() + { + _managed = null; + Unsafe.SkipInit(out _native); + } - public Native ToNativeValue() => _native; + public void FromManaged(MetafileHeaderWmf managed) + { + _managed = managed; + _native.type = managed.type; + _native.size = managed.size; + _native.version = managed.version; + _native.emfPlusFlags = managed.emfPlusFlags; + _native.dpiX = managed.dpiX; + _native.dpiY = managed.dpiY; + _native.X = managed.X; + _native.Y = managed.Y; + _native.Width = managed.Width; + _native.Height = managed.Height; + _native.WmfHeader = managed.WmfHeader.GetNativeValue(); + _native.dummy16 = managed.dummy16; + _native.EmfPlusHeaderSize = managed.EmfPlusHeaderSize; + _native.LogicalDpiX = managed.LogicalDpiX; + _native.LogicalDpiY = managed.LogicalDpiY; + } - public void FromNativeValue(Native value) => _native = value; + public Native ToUnmanaged() => _native; - public MetafileHeaderWmf ToManaged() - { - Debug.Assert(_managed is not null); - _managed.type = _native.type; - _managed.size = _native.size; - _managed.version = _native.version; - _managed.emfPlusFlags = _native.emfPlusFlags; - _managed.dpiX = _native.dpiX; - _managed.dpiY = _native.dpiY; - _managed.X = _native.X; - _managed.Y = _native.Y; - _managed.Width = _native.Width; - _managed.Height = _native.Height; - _managed.WmfHeader = new MetaHeader(_native.WmfHeader); - _managed.dummy16 = _native.dummy16; - _managed.EmfPlusHeaderSize = _native.EmfPlusHeaderSize; - _managed.LogicalDpiX = _native.LogicalDpiX; - _managed.LogicalDpiY = _native.LogicalDpiY; - return _managed; + public void FromUnmanaged(Native value) => _native = value; + + public MetafileHeaderWmf ToManaged() + { + Debug.Assert(_managed is not null); + _managed.type = _native.type; + _managed.size = _native.size; + _managed.version = _native.version; + _managed.emfPlusFlags = _native.emfPlusFlags; + _managed.dpiX = _native.dpiX; + _managed.dpiY = _native.dpiY; + _managed.X = _native.X; + _managed.Y = _native.Y; + _managed.Width = _native.Width; + _managed.Height = _native.Height; + _managed.WmfHeader = new MetaHeader(_native.WmfHeader); + _managed.dummy16 = _native.dummy16; + _managed.EmfPlusHeaderSize = _native.EmfPlusHeaderSize; + _managed.LogicalDpiX = _native.LogicalDpiX; + _managed.LogicalDpiY = _native.LogicalDpiY; + return _managed; + } } - } + } #endif } } From 9a181717f522d9c23a6246999bd2af278f970673 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 5 Jul 2022 15:42:22 -0700 Subject: [PATCH 2/4] Add the required Free methods to the stateful shapes. --- .../System/Runtime/InteropServices/HandleRefMarshaller.cs | 5 +++++ .../System.Drawing.Common/src/System/Drawing/Graphics.cs | 4 ++++ .../System.Drawing.Common/src/System/Drawing/Image.cs | 4 ++++ .../src/System/Drawing/Imaging/MetafileHeaderWmf.cs | 4 ++++ 4 files changed, 17 insertions(+) diff --git a/src/libraries/Common/src/System/Runtime/InteropServices/HandleRefMarshaller.cs b/src/libraries/Common/src/System/Runtime/InteropServices/HandleRefMarshaller.cs index 6ec2f42d71927..a1d2226672dc1 100644 --- a/src/libraries/Common/src/System/Runtime/InteropServices/HandleRefMarshaller.cs +++ b/src/libraries/Common/src/System/Runtime/InteropServices/HandleRefMarshaller.cs @@ -3,6 +3,8 @@ #nullable enable +using System.Diagnostics.CodeAnalysis; + namespace System.Runtime.InteropServices.Marshalling { [CustomMarshaller(typeof(HandleRef), Scenario.ManagedToUnmanagedIn, typeof(KeepAliveMarshaller))] @@ -20,6 +22,9 @@ public void FromManaged(HandleRef handle) public IntPtr ToUnmanaged() => _handle.Handle; public void NotifyInvokeSucceeded() => GC.KeepAlive(_handle.Wrapper); + + [SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "This method is part of the marshaller shape and is required to be an instance method.")] + public void Free() { } } } } diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Graphics.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Graphics.cs index 6c19a7566d287..7bff35e2974bf 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Graphics.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Graphics.cs @@ -11,6 +11,7 @@ using System.Numerics; using System.Runtime.InteropServices; using System.Runtime.Versioning; +using System.Diagnostics.CodeAnalysis; #if NET7_0_OR_GREATER using System.Runtime.InteropServices.Marshalling; #endif @@ -87,6 +88,9 @@ public void NotifyInvokeSucceeded() { GC.KeepAlive(_managed); } + + [SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "This method is part of the marshaller shape and is required to be an instance method.")] + public void Free() { } } } #endif diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Image.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Image.cs index 8170bedf4a183..f93a4efa872fe 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Image.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Image.cs @@ -10,6 +10,7 @@ using System.IO; using System.Runtime.InteropServices; using System.Runtime.Serialization; +using System.Diagnostics.CodeAnalysis; #if NET7_0_OR_GREATER using System.Runtime.InteropServices.Marshalling; #endif @@ -75,6 +76,9 @@ public void NotifyInvokeSucceeded() { GC.KeepAlive(_managed); } + + [SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "This method is part of the marshaller shape and is required to be an instance method.")] + public void Free() { } } } #endif diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/MetafileHeaderWmf.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/MetafileHeaderWmf.cs index a700f949bba1e..aa4eadbd4b65d 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/MetafileHeaderWmf.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/MetafileHeaderWmf.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; #if NET7_0_OR_GREATER @@ -155,6 +156,9 @@ public MetafileHeaderWmf ToManaged() _managed.LogicalDpiY = _native.LogicalDpiY; return _managed; } + + [SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "This method is part of the marshaller shape and is required to be an instance method.")] + public void Free() { } } } #endif From 8f09787b992086dabdbdafa22b4d1ae006ba8c96 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 5 Jul 2022 16:24:19 -0700 Subject: [PATCH 3/4] Move pinnable marshallers to the new model. This moves all non-public (or soon-to-be-public) marshallers over to the new model. --- src/libraries/Common/src/Interop/Interop.Ldap.cs | 16 ++++++---------- .../src/System/Drawing/Imaging/BitmapData.cs | 16 ++++++---------- .../src/System/Drawing/Imaging/ColorMatrix.cs | 16 ++++++---------- .../System/Drawing/Imaging/MetafileHeaderEmf.cs | 16 ++++++---------- .../Drawing/Imaging/WmfPlaceableFileHeader.cs | 16 ++++++---------- 5 files changed, 30 insertions(+), 50 deletions(-) diff --git a/src/libraries/Common/src/Interop/Interop.Ldap.cs b/src/libraries/Common/src/Interop/Interop.Ldap.cs index 040a8b66818de..835b10f7c8996 100644 --- a/src/libraries/Common/src/Interop/Interop.Ldap.cs +++ b/src/libraries/Common/src/Interop/Interop.Ldap.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; #if NET7_0_OR_GREATER @@ -185,18 +186,13 @@ internal sealed class BerVal public IntPtr bv_val = IntPtr.Zero; #if NET7_0_OR_GREATER - [CustomTypeMarshaller(typeof(BerVal), Direction = CustomTypeMarshallerDirection.In, Features = CustomTypeMarshallerFeatures.TwoStageMarshalling)] - internal unsafe struct PinningMarshaller + [CustomMarshaller(typeof(BerVal), Scenario.ManagedToUnmanagedIn, typeof(PinningMarshaller))] + internal static unsafe class PinningMarshaller { - private readonly BerVal _managed; - public PinningMarshaller(BerVal managed) - { - _managed = managed; - } - - public ref int GetPinnableReference() => ref (_managed is null ? ref Unsafe.NullRef() : ref _managed.bv_len); + public static ref int GetPinnableReference(BerVal managed) => ref (managed is null ? ref Unsafe.NullRef() : ref managed.bv_len); - public void* ToNativeValue() => Unsafe.AsPointer(ref GetPinnableReference()); + // All usages in our currently supported scenarios will always go through GetPinnableReference + public static int* ConvertToUnmanaged(BerVal managed) => throw new UnreachableException(); } #endif } diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/BitmapData.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/BitmapData.cs index 9df3935e7d7ec..d9efcca412790 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/BitmapData.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/BitmapData.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; #if NET7_0_OR_GREATER @@ -112,18 +113,13 @@ public int Reserved internal ref int GetPinnableReference() => ref _width; #if NET7_0_OR_GREATER - [CustomTypeMarshaller(typeof(BitmapData), Direction = CustomTypeMarshallerDirection.In, Features = CustomTypeMarshallerFeatures.TwoStageMarshalling)] - internal unsafe struct PinningMarshaller + [CustomMarshaller(typeof(BitmapData), Scenario.ManagedToUnmanagedIn, typeof(PinningMarshaller))] + internal static unsafe class PinningMarshaller { - private readonly BitmapData _managed; - public PinningMarshaller(BitmapData managed) - { - _managed = managed; - } - - public ref int GetPinnableReference() => ref (_managed is null ? ref Unsafe.NullRef() : ref _managed.GetPinnableReference()); + public static ref int GetPinnableReference(BitmapData managed) => ref (managed is null ? ref Unsafe.NullRef() : ref managed.GetPinnableReference()); - public void* ToNativeValue() => Unsafe.AsPointer(ref GetPinnableReference()); + // All usages in our currently supported scenarios will always go through GetPinnableReference + public static int* ConvertToUnmanaged(BitmapData managed) => throw new UnreachableException(); } #endif } diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/ColorMatrix.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/ColorMatrix.cs index f33046ac4a122..0ebed1a9de535 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/ColorMatrix.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/ColorMatrix.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; #if NET7_0_OR_GREATER @@ -399,18 +400,13 @@ internal float[][] GetMatrix() internal ref float GetPinnableReference() => ref _matrix00; #if NET7_0_OR_GREATER - [CustomTypeMarshaller(typeof(ColorMatrix), Direction = CustomTypeMarshallerDirection.In, Features = CustomTypeMarshallerFeatures.TwoStageMarshalling)] - internal unsafe struct PinningMarshaller + [CustomMarshaller(typeof(ColorMatrix), Scenario.ManagedToUnmanagedIn, typeof(PinningMarshaller))] + internal static unsafe class PinningMarshaller { - private readonly ColorMatrix _managed; - public PinningMarshaller(ColorMatrix managed) - { - _managed = managed; - } - - public ref float GetPinnableReference() => ref (_managed is null ? ref Unsafe.NullRef() : ref _managed.GetPinnableReference()); + public static ref float GetPinnableReference(ColorMatrix managed) => ref (managed is null ? ref Unsafe.NullRef() : ref managed.GetPinnableReference()); - public void* ToNativeValue() => Unsafe.AsPointer(ref GetPinnableReference()); + // All usages in our currently supported scenarios will always go through GetPinnableReference + public static float* ConvertToUnmanaged(ColorMatrix managed) => throw new UnreachableException(); } #endif } diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/MetafileHeaderEmf.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/MetafileHeaderEmf.cs index 16951b506fd68..5f879209327ef 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/MetafileHeaderEmf.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/MetafileHeaderEmf.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; #if NET7_0_OR_GREATER @@ -37,18 +38,13 @@ internal sealed class MetafileHeaderEmf internal ref byte GetPinnableReference() => ref Unsafe.As(ref type); #if NET7_0_OR_GREATER - [CustomTypeMarshaller(typeof(MetafileHeaderEmf), Direction = CustomTypeMarshallerDirection.In, Features = CustomTypeMarshallerFeatures.TwoStageMarshalling)] - internal unsafe struct PinningMarshaller + [CustomMarshaller(typeof(MetafileHeaderEmf), Scenario.ManagedToUnmanagedIn, typeof(PinningMarshaller))] + internal static unsafe class PinningMarshaller { - private readonly MetafileHeaderEmf _managed; - public PinningMarshaller(MetafileHeaderEmf managed) - { - _managed = managed; - } + public static ref byte GetPinnableReference(MetafileHeaderEmf managed) => ref (managed is null ? ref Unsafe.NullRef() : ref managed.GetPinnableReference()); - public ref byte GetPinnableReference() => ref (_managed is null ? ref Unsafe.NullRef() : ref _managed.GetPinnableReference()); - - public void* ToNativeValue() => Unsafe.AsPointer(ref GetPinnableReference()); + // All usages in our currently supported scenarios will always go through GetPinnableReference + public static byte* ConvertToUnmanaged(MetafileHeaderEmf managed) => throw new UnreachableException(); } #endif } diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/WmfPlaceableFileHeader.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/WmfPlaceableFileHeader.cs index 006c3296745f3..cfa6173caf101 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/WmfPlaceableFileHeader.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/WmfPlaceableFileHeader.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; #if NET7_0_OR_GREATER @@ -109,18 +110,13 @@ public short Checksum internal ref int GetPinnableReference() => ref _key; #if NET7_0_OR_GREATER - [CustomTypeMarshaller(typeof(WmfPlaceableFileHeader), Direction = CustomTypeMarshallerDirection.In, Features = CustomTypeMarshallerFeatures.TwoStageMarshalling)] - internal unsafe struct PinningMarshaller + [CustomMarshaller(typeof(WmfPlaceableFileHeader), Scenario.ManagedToUnmanagedIn, typeof(PinningMarshaller))] + internal static unsafe class PinningMarshaller { - private readonly WmfPlaceableFileHeader _managed; - public PinningMarshaller(WmfPlaceableFileHeader managed) - { - _managed = managed; - } + public static ref int GetPinnableReference(WmfPlaceableFileHeader managed) => ref (managed is null ? ref Unsafe.NullRef() : ref managed.GetPinnableReference()); - public ref int GetPinnableReference() => ref (_managed is null ? ref Unsafe.NullRef() : ref _managed.GetPinnableReference()); - - public void* ToNativeValue() => Unsafe.AsPointer(ref GetPinnableReference()); + // All usages in our currently supported scenarios will always go through GetPinnableReference + public static int* ConvertToUnmanaged(WmfPlaceableFileHeader managed) => throw new UnreachableException(); } #endif } From 016ecec902a4232621e772cd430090adac02c6f0 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Thu, 7 Jul 2022 11:12:26 -0700 Subject: [PATCH 4/4] Update to approved API shape. Make a few fixes in the generator to improve the development experience. --- src/libraries/Common/src/Interop/Interop.Ldap.cs | 10 +++++----- .../Windows/Advapi32/Interop.LsaLookupNames2.cs | 4 ++-- .../Interop/Windows/WebSocket/Interop.Structs.cs | 4 ++-- .../InteropServices/HandleRefMarshaller.cs | 4 ++-- .../Diagnostics/Reader/UnsafeNativeMethods.cs | 2 +- .../src/System/Drawing/Graphics.cs | 8 ++++---- .../src/System/Drawing/Image.cs | 4 ++-- .../src/System/Drawing/Imaging/BitmapData.cs | 2 +- .../src/System/Drawing/Imaging/ColorMatrix.cs | 2 +- .../System/Drawing/Imaging/MetafileHeaderEmf.cs | 2 +- .../System/Drawing/Imaging/MetafileHeaderWmf.cs | 2 +- .../Drawing/Imaging/WmfPlaceableFileHeader.cs | 2 +- .../ManualTypeMarshallingHelper.cs | 16 +++++++++++----- 13 files changed, 34 insertions(+), 28 deletions(-) diff --git a/src/libraries/Common/src/Interop/Interop.Ldap.cs b/src/libraries/Common/src/Interop/Interop.Ldap.cs index 9ae4e04dcb3a7..7aac37cc97deb 100644 --- a/src/libraries/Common/src/Interop/Interop.Ldap.cs +++ b/src/libraries/Common/src/Interop/Interop.Ldap.cs @@ -186,7 +186,7 @@ internal sealed class BerVal public IntPtr bv_val = IntPtr.Zero; #if NET7_0_OR_GREATER - [CustomMarshaller(typeof(BerVal), Scenario.ManagedToUnmanagedIn, typeof(PinningMarshaller))] + [CustomMarshaller(typeof(BerVal), MarshalMode.ManagedToUnmanagedIn, typeof(PinningMarshaller))] internal static unsafe class PinningMarshaller { public static ref int GetPinnableReference(BerVal managed) => ref (managed is null ? ref Unsafe.NullRef() : ref managed.bv_len); @@ -220,9 +220,9 @@ internal struct LdapReferralCallback #if NET7_0_OR_GREATER public static readonly unsafe int Size = sizeof(Marshaller.MarshalValue.Native); - [CustomMarshaller(typeof(LdapReferralCallback), Scenario.ManagedToUnmanagedIn, typeof(MarshalValue))] - [CustomMarshaller(typeof(LdapReferralCallback), Scenario.ManagedToUnmanagedRef, typeof(MarshalValue))] - [CustomMarshaller(typeof(LdapReferralCallback), Scenario.ManagedToUnmanagedOut, typeof(MarshalValue))] + [CustomMarshaller(typeof(LdapReferralCallback), MarshalMode.ManagedToUnmanagedIn, typeof(MarshalValue))] + [CustomMarshaller(typeof(LdapReferralCallback), MarshalMode.ManagedToUnmanagedRef, typeof(MarshalValue))] + [CustomMarshaller(typeof(LdapReferralCallback), MarshalMode.ManagedToUnmanagedOut, typeof(MarshalValue))] public static class Marshaller { public unsafe struct MarshalValue @@ -262,7 +262,7 @@ public LdapReferralCallback ToManaged() }; } - public void NotifyInvokeSucceeded() => GC.KeepAlive(_managed); + public void OnInvoked() => GC.KeepAlive(_managed); } } #else diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.LsaLookupNames2.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.LsaLookupNames2.cs index e0f4c9f37d0de..bb65329228020 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.LsaLookupNames2.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.LsaLookupNames2.cs @@ -27,8 +27,8 @@ internal struct MARSHALLED_UNICODE_STRING internal ushort MaximumLength; internal string Buffer; - [CustomMarshaller(typeof(MARSHALLED_UNICODE_STRING), Scenario.ManagedToUnmanagedIn, typeof(Marshaller))] - [CustomMarshaller(typeof(MARSHALLED_UNICODE_STRING), Scenario.ElementIn, typeof(Marshaller))] + [CustomMarshaller(typeof(MARSHALLED_UNICODE_STRING), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))] + [CustomMarshaller(typeof(MARSHALLED_UNICODE_STRING), MarshalMode.ElementIn, typeof(Marshaller))] public static class Marshaller { public static Native ConvertToUnmanaged(MARSHALLED_UNICODE_STRING managed) diff --git a/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.Structs.cs b/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.Structs.cs index 59cf02a950de3..8cb4cc8333ff3 100644 --- a/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.Structs.cs +++ b/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.Structs.cs @@ -50,8 +50,8 @@ internal struct HttpHeader internal string Value; internal uint ValueLength; - [CustomMarshaller(typeof(HttpHeader), Scenario.ManagedToUnmanagedIn, typeof(Marshaller))] - [CustomMarshaller(typeof(HttpHeader), Scenario.ElementIn, typeof(Marshaller))] + [CustomMarshaller(typeof(HttpHeader), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))] + [CustomMarshaller(typeof(HttpHeader), MarshalMode.ElementIn, typeof(Marshaller))] public static class Marshaller { public static Native ConvertToUnmanaged(HttpHeader managed) diff --git a/src/libraries/Common/src/System/Runtime/InteropServices/HandleRefMarshaller.cs b/src/libraries/Common/src/System/Runtime/InteropServices/HandleRefMarshaller.cs index a1d2226672dc1..ccdfa9d55d984 100644 --- a/src/libraries/Common/src/System/Runtime/InteropServices/HandleRefMarshaller.cs +++ b/src/libraries/Common/src/System/Runtime/InteropServices/HandleRefMarshaller.cs @@ -7,7 +7,7 @@ namespace System.Runtime.InteropServices.Marshalling { - [CustomMarshaller(typeof(HandleRef), Scenario.ManagedToUnmanagedIn, typeof(KeepAliveMarshaller))] + [CustomMarshaller(typeof(HandleRef), MarshalMode.ManagedToUnmanagedIn, typeof(KeepAliveMarshaller))] internal static class HandleRefMarshaller { internal struct KeepAliveMarshaller @@ -21,7 +21,7 @@ public void FromManaged(HandleRef handle) public IntPtr ToUnmanaged() => _handle.Handle; - public void NotifyInvokeSucceeded() => GC.KeepAlive(_handle.Wrapper); + public void OnInvoked() => GC.KeepAlive(_handle.Wrapper); [SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "This method is part of the marshaller shape and is required to be an instance method.")] public void Free() { } diff --git a/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/UnsafeNativeMethods.cs b/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/UnsafeNativeMethods.cs index 4211cd134cd96..21ce94d0c423f 100644 --- a/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/UnsafeNativeMethods.cs +++ b/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/UnsafeNativeMethods.cs @@ -356,7 +356,7 @@ internal struct EvtRpcLogin public CoTaskMemUnicodeSafeHandle Password; public int Flags; #if NET7_0_OR_GREATER - [CustomMarshaller(typeof(EvtRpcLogin), Scenario.ManagedToUnmanagedRef, typeof(ValueMarshaller))] + [CustomMarshaller(typeof(EvtRpcLogin), MarshalMode.ManagedToUnmanagedRef, typeof(ValueMarshaller))] public static class Marshaller { public struct ValueMarshaller diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Graphics.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Graphics.cs index 7bff35e2974bf..34ccdb709b3a2 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Graphics.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Graphics.cs @@ -65,7 +65,7 @@ internal static string GetAllocationStack() { public delegate bool DrawImageAbort(IntPtr callbackdata); #if NET7_0_OR_GREATER - [CustomMarshaller(typeof(DrawImageAbort), Scenario.ManagedToUnmanagedIn, typeof(KeepAliveMarshaller))] + [CustomMarshaller(typeof(DrawImageAbort), MarshalMode.ManagedToUnmanagedIn, typeof(KeepAliveMarshaller))] internal static class DrawImageAbortMarshaller { internal unsafe struct KeepAliveMarshaller @@ -84,7 +84,7 @@ public void FromManaged(DrawImageAbort? managed) return _nativeFunction; } - public void NotifyInvokeSucceeded() + public void OnInvoked() { GC.KeepAlive(_managed); } @@ -113,7 +113,7 @@ public delegate bool EnumerateMetafileProc( PlayRecordCallback? callbackData); #if NET7_0_OR_GREATER - [CustomMarshaller(typeof(EnumerateMetafileProc), Scenario.ManagedToUnmanagedIn, typeof(KeepAliveMarshaller))] + [CustomMarshaller(typeof(EnumerateMetafileProc), MarshalMode.ManagedToUnmanagedIn, typeof(KeepAliveMarshaller))] internal static class EnumerateMetafileProcMarshaller { internal unsafe struct KeepAliveMarshaller @@ -138,7 +138,7 @@ public void FromManaged(EnumerateMetafileProc? managed) return _nativeFunction; } - public void NotifyInvokeSucceeded() + public void OnInvoked() { GC.KeepAlive(_managed); } diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Image.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Image.cs index f93a4efa872fe..0cb8b907aa498 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Image.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Image.cs @@ -45,7 +45,7 @@ public abstract class Image : MarshalByRefObject, IDisposable, ICloneable, ISeri public delegate bool GetThumbnailImageAbort(); #if NET7_0_OR_GREATER - [CustomMarshaller(typeof(GetThumbnailImageAbort), Scenario.ManagedToUnmanagedIn, typeof(KeepAliveMarshaller))] + [CustomMarshaller(typeof(GetThumbnailImageAbort), MarshalMode.ManagedToUnmanagedIn, typeof(KeepAliveMarshaller))] internal static class GetThumbnailImageAbortMarshaller { internal unsafe struct KeepAliveMarshaller @@ -72,7 +72,7 @@ public void FromManaged(GetThumbnailImageAbort managed) return _nativeFunction; } - public void NotifyInvokeSucceeded() + public void OnInvoked() { GC.KeepAlive(_managed); } diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/BitmapData.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/BitmapData.cs index d9efcca412790..759ff7b1b158a 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/BitmapData.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/BitmapData.cs @@ -113,7 +113,7 @@ public int Reserved internal ref int GetPinnableReference() => ref _width; #if NET7_0_OR_GREATER - [CustomMarshaller(typeof(BitmapData), Scenario.ManagedToUnmanagedIn, typeof(PinningMarshaller))] + [CustomMarshaller(typeof(BitmapData), MarshalMode.ManagedToUnmanagedIn, typeof(PinningMarshaller))] internal static unsafe class PinningMarshaller { public static ref int GetPinnableReference(BitmapData managed) => ref (managed is null ? ref Unsafe.NullRef() : ref managed.GetPinnableReference()); diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/ColorMatrix.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/ColorMatrix.cs index 0ebed1a9de535..75d090894f463 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/ColorMatrix.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/ColorMatrix.cs @@ -400,7 +400,7 @@ internal float[][] GetMatrix() internal ref float GetPinnableReference() => ref _matrix00; #if NET7_0_OR_GREATER - [CustomMarshaller(typeof(ColorMatrix), Scenario.ManagedToUnmanagedIn, typeof(PinningMarshaller))] + [CustomMarshaller(typeof(ColorMatrix), MarshalMode.ManagedToUnmanagedIn, typeof(PinningMarshaller))] internal static unsafe class PinningMarshaller { public static ref float GetPinnableReference(ColorMatrix managed) => ref (managed is null ? ref Unsafe.NullRef() : ref managed.GetPinnableReference()); diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/MetafileHeaderEmf.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/MetafileHeaderEmf.cs index 5f879209327ef..b28b757f9493d 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/MetafileHeaderEmf.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/MetafileHeaderEmf.cs @@ -38,7 +38,7 @@ internal sealed class MetafileHeaderEmf internal ref byte GetPinnableReference() => ref Unsafe.As(ref type); #if NET7_0_OR_GREATER - [CustomMarshaller(typeof(MetafileHeaderEmf), Scenario.ManagedToUnmanagedIn, typeof(PinningMarshaller))] + [CustomMarshaller(typeof(MetafileHeaderEmf), MarshalMode.ManagedToUnmanagedIn, typeof(PinningMarshaller))] internal static unsafe class PinningMarshaller { public static ref byte GetPinnableReference(MetafileHeaderEmf managed) => ref (managed is null ? ref Unsafe.NullRef() : ref managed.GetPinnableReference()); diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/MetafileHeaderWmf.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/MetafileHeaderWmf.cs index aa4eadbd4b65d..f984b287c0f00 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/MetafileHeaderWmf.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/MetafileHeaderWmf.cs @@ -59,7 +59,7 @@ internal sealed class MetafileHeaderWmf public int LogicalDpiY; #if NET7_0_OR_GREATER - [CustomMarshaller(typeof(MetafileHeaderWmf), Scenario.ManagedToUnmanagedRef, typeof(InPlaceMarshaller))] + [CustomMarshaller(typeof(MetafileHeaderWmf), MarshalMode.ManagedToUnmanagedRef, typeof(InPlaceMarshaller))] internal static class Marshaller { internal unsafe struct InPlaceMarshaller diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/WmfPlaceableFileHeader.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/WmfPlaceableFileHeader.cs index cfa6173caf101..f9d3baa6557ee 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/WmfPlaceableFileHeader.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/WmfPlaceableFileHeader.cs @@ -110,7 +110,7 @@ public short Checksum internal ref int GetPinnableReference() => ref _key; #if NET7_0_OR_GREATER - [CustomMarshaller(typeof(WmfPlaceableFileHeader), Scenario.ManagedToUnmanagedIn, typeof(PinningMarshaller))] + [CustomMarshaller(typeof(WmfPlaceableFileHeader), MarshalMode.ManagedToUnmanagedIn, typeof(PinningMarshaller))] internal static unsafe class PinningMarshaller { public static ref int GetPinnableReference(WmfPlaceableFileHeader managed) => ref (managed is null ? ref Unsafe.NullRef() : ref managed.GetPinnableReference()); diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManualTypeMarshallingHelper.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManualTypeMarshallingHelper.cs index 568fc4ff11185..0dae64e06bcc3 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManualTypeMarshallingHelper.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManualTypeMarshallingHelper.cs @@ -117,8 +117,16 @@ private static bool TryGetMarshallersFromEntryType( Debug.Assert(!isLinearCollectionMarshalling || getMarshallingInfoForElement is not null); Dictionary modes = new(); + foreach (AttributeData attr in attrs) { + if (attr.AttributeConstructor is null) + { + // If the attribute constructor couldn't be bound by the compiler, then we shouldn't try to extract the constructor arguments. + // Roslyn doesn't provide them if it can't bind the constructor. + // We don't report a diagnostic here since Roslyn will report a diagnostic anyway. + continue; + } Debug.Assert(attr.ConstructorArguments.Length == 3); // Verify the defined marshaller is for the managed type. @@ -167,7 +175,7 @@ private static bool TryGetMarshallersFromEntryType( marshallerType = currentType; } - // TODO: We can probably get rid of MarshallingDirection and just use Scenario instead + // TODO: We can probably get rid of MarshallingDirection and just use MarshalMode instead MarshallingDirection direction = marshalMode switch { MarshalMode.Default @@ -175,19 +183,17 @@ private static bool TryGetMarshallersFromEntryType( MarshalMode.ManagedToUnmanagedIn or MarshalMode.UnmanagedToManagedOut + or MarshalMode.ElementIn => MarshallingDirection.ManagedToUnmanaged, MarshalMode.ManagedToUnmanagedOut or MarshalMode.UnmanagedToManagedIn + or MarshalMode.ElementOut => MarshallingDirection.UnmanagedToManaged, MarshalMode.ManagedToUnmanagedRef or MarshalMode.UnmanagedToManagedRef - => MarshallingDirection.Bidirectional, - - MarshalMode.ElementIn or MarshalMode.ElementRef - or MarshalMode.ElementOut => MarshallingDirection.Bidirectional, _ => throw new UnreachableException()