Skip to content

Commit 0c631ab

Browse files
authored
Update all internal marshallers to the new model (#71470)
1 parent 8e0a132 commit 0c631ab

14 files changed

Lines changed: 362 additions & 314 deletions

File tree

src/libraries/Common/src/Interop/Interop.Ldap.cs

Lines changed: 42 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System.Diagnostics;
45
using System.Runtime.CompilerServices;
56
using System.Runtime.InteropServices;
67
#if NET7_0_OR_GREATER
@@ -185,18 +186,13 @@ internal sealed class BerVal
185186
public IntPtr bv_val = IntPtr.Zero;
186187

187188
#if NET7_0_OR_GREATER
188-
[CustomTypeMarshaller(typeof(BerVal), Direction = CustomTypeMarshallerDirection.In, Features = CustomTypeMarshallerFeatures.TwoStageMarshalling)]
189-
internal unsafe struct PinningMarshaller
189+
[CustomMarshaller(typeof(BerVal), MarshalMode.ManagedToUnmanagedIn, typeof(PinningMarshaller))]
190+
internal static unsafe class PinningMarshaller
190191
{
191-
private readonly BerVal _managed;
192-
public PinningMarshaller(BerVal managed)
193-
{
194-
_managed = managed;
195-
}
196-
197-
public ref int GetPinnableReference() => ref (_managed is null ? ref Unsafe.NullRef<int>() : ref _managed.bv_len);
192+
public static ref int GetPinnableReference(BerVal managed) => ref (managed is null ? ref Unsafe.NullRef<int>() : ref managed.bv_len);
198193

199-
public void* ToNativeValue() => Unsafe.AsPointer(ref GetPinnableReference());
194+
// All usages in our currently supported scenarios will always go through GetPinnableReference
195+
public static int* ConvertToUnmanaged(BerVal managed) => throw new UnreachableException();
200196
}
201197
#endif
202198
}
@@ -222,48 +218,52 @@ internal struct LdapReferralCallback
222218
public NOTIFYOFNEWCONNECTIONInternal notify;
223219
public DEREFERENCECONNECTIONInternal dereference;
224220
#if NET7_0_OR_GREATER
225-
public static readonly unsafe int Size = sizeof(Marshaller.Native);
221+
public static readonly unsafe int Size = sizeof(Marshaller.MarshalValue.Native);
226222

227-
[CustomTypeMarshaller(typeof(LdapReferralCallback), Features = CustomTypeMarshallerFeatures.UnmanagedResources | CustomTypeMarshallerFeatures.TwoStageMarshalling)]
228-
public unsafe struct Marshaller
223+
[CustomMarshaller(typeof(LdapReferralCallback), MarshalMode.ManagedToUnmanagedIn, typeof(MarshalValue))]
224+
[CustomMarshaller(typeof(LdapReferralCallback), MarshalMode.ManagedToUnmanagedRef, typeof(MarshalValue))]
225+
[CustomMarshaller(typeof(LdapReferralCallback), MarshalMode.ManagedToUnmanagedOut, typeof(MarshalValue))]
226+
public static class Marshaller
229227
{
230-
public unsafe struct Native
228+
public unsafe struct MarshalValue
231229
{
232-
public int sizeofcallback;
233-
public IntPtr query;
234-
public IntPtr notify;
235-
public IntPtr dereference;
236-
}
230+
public unsafe struct Native
231+
{
232+
public int sizeofcallback;
233+
public IntPtr query;
234+
public IntPtr notify;
235+
public IntPtr dereference;
236+
}
237237

238-
private LdapReferralCallback _managed;
239-
private Native _native;
238+
private LdapReferralCallback _managed;
239+
private Native _native;
240240

241-
public Marshaller(LdapReferralCallback managed)
242-
: this()
243-
{
244-
_managed = managed;
245-
_native.sizeofcallback = sizeof(Native);
246-
_native.query = managed.query is not null ? Marshal.GetFunctionPointerForDelegate(managed.query) : IntPtr.Zero;
247-
_native.notify = managed.notify is not null ? Marshal.GetFunctionPointerForDelegate(managed.notify) : IntPtr.Zero;
248-
_native.dereference = managed.dereference is not null ? Marshal.GetFunctionPointerForDelegate(managed.dereference) : IntPtr.Zero;
249-
}
241+
public void FromManaged(LdapReferralCallback managed)
242+
{
243+
_managed = managed;
244+
_native.sizeofcallback = sizeof(Native);
245+
_native.query = managed.query is not null ? Marshal.GetFunctionPointerForDelegate(managed.query) : IntPtr.Zero;
246+
_native.notify = managed.notify is not null ? Marshal.GetFunctionPointerForDelegate(managed.notify) : IntPtr.Zero;
247+
_native.dereference = managed.dereference is not null ? Marshal.GetFunctionPointerForDelegate(managed.dereference) : IntPtr.Zero;
248+
}
250249

251-
public Native ToNativeValue() => _native;
250+
public Native ToUnmanaged() => _native;
252251

253-
public void FromNativeValue(Native value) => _native = value;
252+
public void FromUnmanaged(Native value) => _native = value;
254253

255-
public LdapReferralCallback ToManaged()
256-
{
257-
return new LdapReferralCallback()
254+
public LdapReferralCallback ToManaged()
258255
{
259-
sizeofcallback = _native.sizeofcallback,
260-
query = _native.query != IntPtr.Zero ? Marshal.GetDelegateForFunctionPointer<QUERYFORCONNECTIONInternal>(_native.query) : null,
261-
notify = _native.notify != IntPtr.Zero ? Marshal.GetDelegateForFunctionPointer<NOTIFYOFNEWCONNECTIONInternal>(_native.notify) : null,
262-
dereference = _native.dereference != IntPtr.Zero ? Marshal.GetDelegateForFunctionPointer<DEREFERENCECONNECTIONInternal>(_native.dereference) : null
263-
};
256+
return new LdapReferralCallback()
257+
{
258+
sizeofcallback = _native.sizeofcallback,
259+
query = _native.query != IntPtr.Zero ? Marshal.GetDelegateForFunctionPointer<QUERYFORCONNECTIONInternal>(_native.query) : null,
260+
notify = _native.notify != IntPtr.Zero ? Marshal.GetDelegateForFunctionPointer<NOTIFYOFNEWCONNECTIONInternal>(_native.notify) : null,
261+
dereference = _native.dereference != IntPtr.Zero ? Marshal.GetDelegateForFunctionPointer<DEREFERENCECONNECTIONInternal>(_native.dereference) : null
262+
};
263+
}
264+
265+
public void OnInvoked() => GC.KeepAlive(_managed);
264266
}
265-
266-
public void FreeNative() => GC.KeepAlive(_managed);
267267
}
268268
#else
269269
public static readonly unsafe int Size = Marshal.SizeOf<LdapReferralCallback>();

src/libraries/Common/src/Interop/Windows/Advapi32/Interop.LsaLookupNames2.cs

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,28 +20,37 @@ internal static partial uint LsaLookupNames2(
2020
out SafeLsaMemoryHandle sids
2121
);
2222

23-
[NativeMarshalling(typeof(Native))]
23+
[NativeMarshalling(typeof(Marshaller))]
2424
internal struct MARSHALLED_UNICODE_STRING
2525
{
2626
internal ushort Length;
2727
internal ushort MaximumLength;
2828
internal string Buffer;
2929

30-
[CustomTypeMarshaller(typeof(MARSHALLED_UNICODE_STRING), Direction = CustomTypeMarshallerDirection.In, Features = CustomTypeMarshallerFeatures.UnmanagedResources)]
31-
public struct Native
30+
[CustomMarshaller(typeof(MARSHALLED_UNICODE_STRING), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))]
31+
[CustomMarshaller(typeof(MARSHALLED_UNICODE_STRING), MarshalMode.ElementIn, typeof(Marshaller))]
32+
public static class Marshaller
3233
{
33-
internal ushort Length;
34-
internal ushort MaximumLength;
35-
internal IntPtr Buffer;
34+
public static Native ConvertToUnmanaged(MARSHALLED_UNICODE_STRING managed)
35+
{
36+
Native n;
37+
n.Length = managed.Length;
38+
n.MaximumLength = managed.MaximumLength;
39+
n.Buffer = Marshal.StringToCoTaskMemUni(managed.Buffer);
40+
return n;
41+
}
3642

37-
public Native(MARSHALLED_UNICODE_STRING managed)
43+
public static void Free(Native native)
3844
{
39-
Length = managed.Length;
40-
MaximumLength = managed.MaximumLength;
41-
Buffer = Marshal.StringToCoTaskMemUni(managed.Buffer);
45+
Marshal.FreeCoTaskMem(native.Buffer);
4246
}
4347

44-
public void FreeNative() => Marshal.FreeCoTaskMem(Buffer);
48+
public struct Native
49+
{
50+
internal ushort Length;
51+
internal ushort MaximumLength;
52+
internal IntPtr Buffer;
53+
}
4554
}
4655
}
4756
}

src/libraries/Common/src/Interop/Windows/WebSocket/Interop.Structs.cs

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -42,34 +42,40 @@ internal struct CloseBuffer
4242
internal ushort CloseStatus;
4343
}
4444

45-
[NativeMarshalling(typeof(Native))]
45+
[NativeMarshalling(typeof(Marshaller))]
4646
internal struct HttpHeader
4747
{
4848
internal string Name;
4949
internal uint NameLength;
5050
internal string Value;
5151
internal uint ValueLength;
5252

53-
[CustomTypeMarshaller(typeof(HttpHeader), Direction = CustomTypeMarshallerDirection.In, Features = CustomTypeMarshallerFeatures.UnmanagedResources)]
54-
internal struct Native
53+
[CustomMarshaller(typeof(HttpHeader), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))]
54+
[CustomMarshaller(typeof(HttpHeader), MarshalMode.ElementIn, typeof(Marshaller))]
55+
public static class Marshaller
5556
{
56-
private IntPtr Name;
57-
private uint NameLength;
58-
private IntPtr Value;
59-
private uint ValueLength;
57+
public static Native ConvertToUnmanaged(HttpHeader managed)
58+
{
59+
Native n;
60+
n.Name = Marshal.StringToCoTaskMemAnsi(managed.Name);
61+
n.NameLength = managed.NameLength;
62+
n.Value = Marshal.StringToCoTaskMemAnsi(managed.Value);
63+
n.ValueLength = managed.ValueLength;
64+
return n;
65+
}
6066

61-
public Native(HttpHeader managed)
67+
public static void Free(Native n)
6268
{
63-
Name = Marshal.StringToCoTaskMemAnsi(managed.Name);
64-
NameLength = managed.NameLength;
65-
Value = Marshal.StringToCoTaskMemAnsi(managed.Value);
66-
ValueLength = managed.ValueLength;
69+
Marshal.FreeCoTaskMem(n.Name);
70+
Marshal.FreeCoTaskMem(n.Value);
6771
}
6872

69-
public void FreeNative()
73+
internal struct Native
7074
{
71-
Marshal.FreeCoTaskMem(Name);
72-
Marshal.FreeCoTaskMem(Value);
75+
public IntPtr Name;
76+
public uint NameLength;
77+
public IntPtr Value;
78+
public uint ValueLength;
7379
}
7480
}
7581
}

src/libraries/Common/src/System/Runtime/InteropServices/HandleRefMarshaller.cs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,28 @@
33

44
#nullable enable
55

6+
using System.Diagnostics.CodeAnalysis;
7+
68
namespace System.Runtime.InteropServices.Marshalling
79
{
8-
[CustomTypeMarshaller(typeof(HandleRef), Direction = CustomTypeMarshallerDirection.In, Features = CustomTypeMarshallerFeatures.UnmanagedResources | CustomTypeMarshallerFeatures.TwoStageMarshalling)]
9-
internal struct HandleRefMarshaller
10+
[CustomMarshaller(typeof(HandleRef), MarshalMode.ManagedToUnmanagedIn, typeof(KeepAliveMarshaller))]
11+
internal static class HandleRefMarshaller
1012
{
11-
private HandleRef _handle;
12-
13-
public HandleRefMarshaller(HandleRef handle)
13+
internal struct KeepAliveMarshaller
1414
{
15-
_handle = handle;
16-
}
15+
private HandleRef _handle;
1716

18-
public IntPtr ToNativeValue() => _handle.Handle;
17+
public void FromManaged(HandleRef handle)
18+
{
19+
_handle = handle;
20+
}
1921

20-
public void FreeNative() => GC.KeepAlive(_handle.Wrapper);
22+
public IntPtr ToUnmanaged() => _handle.Handle;
23+
24+
public void OnInvoked() => GC.KeepAlive(_handle.Wrapper);
25+
26+
[SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "This method is part of the marshaller shape and is required to be an instance method.")]
27+
public void Free() { }
28+
}
2129
}
2230
}

src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/UnsafeNativeMethods.cs

Lines changed: 54 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -356,66 +356,72 @@ internal struct EvtRpcLogin
356356
public CoTaskMemUnicodeSafeHandle Password;
357357
public int Flags;
358358
#if NET7_0_OR_GREATER
359-
[CustomTypeMarshaller(typeof(EvtRpcLogin), Features = CustomTypeMarshallerFeatures.UnmanagedResources | CustomTypeMarshallerFeatures.TwoStageMarshalling)]
360-
public struct Marshaller
359+
[CustomMarshaller(typeof(EvtRpcLogin), MarshalMode.ManagedToUnmanagedRef, typeof(ValueMarshaller))]
360+
public static class Marshaller
361361
{
362-
public struct Native
362+
public struct ValueMarshaller
363363
{
364-
public IntPtr Server;
365-
public IntPtr User;
366-
public IntPtr Domain;
367-
public IntPtr Password;
368-
public int Flags;
369-
}
364+
public struct Native
365+
{
366+
public IntPtr Server;
367+
public IntPtr User;
368+
public IntPtr Domain;
369+
public IntPtr Password;
370+
public int Flags;
371+
}
370372

371-
private CoTaskMemUnicodeSafeHandle _passwordHandle;
372-
private Native _value;
373-
private bool _passwordHandleAddRefd;
373+
private CoTaskMemUnicodeSafeHandle _passwordHandle;
374+
private IntPtr _originalHandleValue;
375+
private Native _value;
376+
private bool _passwordHandleAddRefd;
374377

375-
public Marshaller(EvtRpcLogin managed)
376-
{
377-
_passwordHandleAddRefd = false;
378-
_value.Server = Marshal.StringToCoTaskMemUni(managed.Server);
379-
_value.User = Marshal.StringToCoTaskMemUni(managed.User);
380-
_value.Domain = Marshal.StringToCoTaskMemUni(managed.Domain);
381-
_passwordHandle = managed.Password;
382-
_passwordHandle.DangerousAddRef(ref _passwordHandleAddRefd);
383-
_value.Password = _passwordHandle.DangerousGetHandle();
384-
_value.Flags = managed.Flags;
385-
}
378+
public void FromManaged(EvtRpcLogin managed)
379+
{
380+
_passwordHandleAddRefd = false;
381+
_value.Server = Marshal.StringToCoTaskMemUni(managed.Server);
382+
_value.User = Marshal.StringToCoTaskMemUni(managed.User);
383+
_value.Domain = Marshal.StringToCoTaskMemUni(managed.Domain);
384+
_passwordHandle = managed.Password;
385+
_passwordHandle.DangerousAddRef(ref _passwordHandleAddRefd);
386+
_value.Password = _originalHandleValue = _passwordHandle.DangerousGetHandle();
387+
_value.Flags = managed.Flags;
388+
}
386389

387-
public Native ToNativeValue() => _value;
390+
public Native ToUnmanaged() => _value;
388391

389-
public void FromNativeValue(Native value)
390-
{
391-
// SafeHandle fields cannot change the underlying handle value during marshalling.
392-
if (_value.Password != value.Password)
392+
public void FromUnmanaged(Native value)
393393
{
394-
throw new InvalidOperationException();
394+
_value = value;
395395
}
396-
_value = value;
397-
}
398396

399-
public EvtRpcLogin ToManaged()
400-
{
401-
return new EvtRpcLogin
397+
public EvtRpcLogin ToManaged()
402398
{
403-
Server = Marshal.PtrToStringUni(_value.Server),
404-
User = Marshal.PtrToStringUni(_value.User),
405-
Domain = Marshal.PtrToStringUni(_value.Domain),
406-
Password = _passwordHandle,
407-
Flags = _value.Flags
408-
};
409-
}
399+
// SafeHandle fields cannot change the underlying handle value during marshalling.
400+
if (_value.Password != _originalHandleValue)
401+
{
402+
// Match the same exception type that the built-in marshalling throws.
403+
throw new NotSupportedException();
404+
}
410405

411-
public void FreeNative()
412-
{
413-
Marshal.FreeCoTaskMem(_value.Server);
414-
Marshal.FreeCoTaskMem(_value.User);
415-
Marshal.FreeCoTaskMem(_value.Domain);
416-
if (_passwordHandleAddRefd)
406+
return new EvtRpcLogin
407+
{
408+
Server = Marshal.PtrToStringUni(_value.Server),
409+
User = Marshal.PtrToStringUni(_value.User),
410+
Domain = Marshal.PtrToStringUni(_value.Domain),
411+
Password = _passwordHandle,
412+
Flags = _value.Flags
413+
};
414+
}
415+
416+
public void Free()
417417
{
418-
_passwordHandle.DangerousRelease();
418+
Marshal.FreeCoTaskMem(_value.Server);
419+
Marshal.FreeCoTaskMem(_value.User);
420+
Marshal.FreeCoTaskMem(_value.Domain);
421+
if (_passwordHandleAddRefd)
422+
{
423+
_passwordHandle.DangerousRelease();
424+
}
419425
}
420426
}
421427
}

src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4384,7 +4384,7 @@ private static partial int GdipGetMetafileHeaderFromWmf_Internal(IntPtr hMetafil
43844384
#endif
43854385
WmfPlaceableFileHeader wmfplaceable,
43864386
#if NET7_0_OR_GREATER
4387-
[MarshalUsing(typeof(MetafileHeaderWmf.InPlaceMarshaller))]
4387+
[MarshalUsing(typeof(MetafileHeaderWmf.Marshaller))]
43884388
ref MetafileHeaderWmf metafileHeaderWmf
43894389
#else
43904390
MetafileHeaderWmf metafileHeaderWmf

0 commit comments

Comments
 (0)