Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update all internal marshallers to the new model #71470

Merged
merged 6 commits into from
Jul 7, 2022
84 changes: 42 additions & 42 deletions src/libraries/Common/src/Interop/Interop.Ldap.cs
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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), MarshalMode.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<int>() : ref _managed.bv_len);
public static ref int GetPinnableReference(BerVal managed) => ref (managed is null ? ref Unsafe.NullRef<int>() : 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
}
Expand All @@ -222,48 +218,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), 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 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<QUERYFORCONNECTIONInternal>(_native.query) : null,
notify = _native.notify != IntPtr.Zero ? Marshal.GetDelegateForFunctionPointer<NOTIFYOFNEWCONNECTIONInternal>(_native.notify) : null,
dereference = _native.dereference != IntPtr.Zero ? Marshal.GetDelegateForFunctionPointer<DEREFERENCECONNECTIONInternal>(_native.dereference) : null
};
return new LdapReferralCallback()
{
sizeofcallback = _native.sizeofcallback,
query = _native.query != IntPtr.Zero ? Marshal.GetDelegateForFunctionPointer<QUERYFORCONNECTIONInternal>(_native.query) : null,
notify = _native.notify != IntPtr.Zero ? Marshal.GetDelegateForFunctionPointer<NOTIFYOFNEWCONNECTIONInternal>(_native.notify) : null,
dereference = _native.dereference != IntPtr.Zero ? Marshal.GetDelegateForFunctionPointer<DEREFERENCECONNECTIONInternal>(_native.dereference) : null
};
}

public void OnInvoked() => GC.KeepAlive(_managed);
}

public void FreeNative() => GC.KeepAlive(_managed);
}
#else
public static readonly unsafe int Size = Marshal.SizeOf<LdapReferralCallback>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))]
[CustomMarshaller(typeof(MARSHALLED_UNICODE_STRING), MarshalMode.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;
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,34 +42,40 @@ internal struct CloseBuffer
internal ushort CloseStatus;
}

[NativeMarshalling(typeof(Native))]
[NativeMarshalling(typeof(Marshaller))]
internal struct HttpHeader
{
internal string Name;
internal uint NameLength;
internal string Value;
internal uint ValueLength;

[CustomTypeMarshaller(typeof(HttpHeader), Direction = CustomTypeMarshallerDirection.In, Features = CustomTypeMarshallerFeatures.UnmanagedResources)]
internal struct Native
[CustomMarshaller(typeof(HttpHeader), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))]
[CustomMarshaller(typeof(HttpHeader), MarshalMode.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;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,28 @@

#nullable enable

using System.Diagnostics.CodeAnalysis;

namespace System.Runtime.InteropServices.Marshalling
{
[CustomTypeMarshaller(typeof(HandleRef), Direction = CustomTypeMarshallerDirection.In, Features = CustomTypeMarshallerFeatures.UnmanagedResources | CustomTypeMarshallerFeatures.TwoStageMarshalling)]
internal struct HandleRefMarshaller
[CustomMarshaller(typeof(HandleRef), MarshalMode.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 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() { }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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), MarshalMode.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();
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading