From 665fe1374cb0213bf259adf91a65b0b5739dbc09 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 15 Apr 2026 21:06:52 +0000 Subject: [PATCH 1/2] Use ComVariant in GetNativeVariantForObject tests Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/b87f2dcb-ecea-4af2-b091-551b6de94281 Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com> --- ...ystem.Runtime.InteropServices.Tests.csproj | 1 - .../InteropServices/Marshal/Common/Variant.cs | 17 ----- .../GetNativeVariantForObjectTests.Windows.cs | 4 +- .../Marshal/GetNativeVariantForObjectTests.cs | 73 +++++++++---------- 4 files changed, 38 insertions(+), 57 deletions(-) delete mode 100644 src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/Common/Variant.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System.Runtime.InteropServices.Tests.csproj b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System.Runtime.InteropServices.Tests.csproj index acb1d91dae2d82..9ebc831152ff28 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System.Runtime.InteropServices.Tests.csproj +++ b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System.Runtime.InteropServices.Tests.csproj @@ -141,7 +141,6 @@ - diff --git a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/Common/Variant.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/Common/Variant.cs deleted file mode 100644 index bc97d99bb052a2..00000000000000 --- a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/Common/Variant.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.Runtime.InteropServices.Tests.Common -{ - public struct Variant - { -#pragma warning disable 0649 - public ushort vt; - public ushort wReserved1; - public ushort wReserved2; - public ushort wReserved3; - public IntPtr bstrVal; - public IntPtr pRecInfo; -#pragma warning restore 0649 - } -} diff --git a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetNativeVariantForObjectTests.Windows.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetNativeVariantForObjectTests.Windows.cs index ea466ac7d31767..0b6737a8326307 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetNativeVariantForObjectTests.Windows.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetNativeVariantForObjectTests.Windows.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Runtime.InteropServices.Marshalling; using System.Runtime.InteropServices.Tests.Common; using Xunit; @@ -108,8 +109,7 @@ public static IEnumerable GetNativeVariantForObject_InvalidArrayType_T [MemberData(nameof(GetNativeVariantForObject_InvalidArrayType_TestData))] public void GetNativeVariantForObject_InvalidArrayType_ThrowsInvalidCastException(object obj) { - Variant v = new Variant(); - IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v)); + IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf()); try { Assert.Throws(() => Marshal.GetNativeVariantForObject(obj, pNative)); diff --git a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetNativeVariantForObjectTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetNativeVariantForObjectTests.cs index 108a842a3c8b39..af116064127e2d 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetNativeVariantForObjectTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetNativeVariantForObjectTests.cs @@ -5,6 +5,7 @@ using System.Drawing; using System.Reflection; using System.Reflection.Emit; +using System.Runtime.InteropServices.Marshalling; using System.Runtime.InteropServices.Tests.Common; using Xunit; @@ -109,22 +110,21 @@ public static IEnumerable GetNativeVariantForObject_NonRoundtrippingPr [MemberData(nameof(GetNativeVariantForObject_NonRoundtrippingPrimitives_TestData))] public void GetNativeVariantForObject_ValidObject_Success(object primitive, VarEnum expectedVarType, IntPtr expectedValue, object expectedRoundtripValue) { - var v = new Variant(); - IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v)); + IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf()); try { Marshal.GetNativeVariantForObject(primitive, pNative); - Variant result = Marshal.PtrToStructure(pNative); - Assert.Equal(expectedVarType, (VarEnum)result.vt); + ComVariant result = Marshal.PtrToStructure(pNative); + Assert.Equal(expectedVarType, result.VarType); if (expectedValue != (IntPtr)(-1)) { - Assert.Equal(expectedValue, result.bstrVal); + Assert.Equal(expectedValue, result.GetRawDataRef()); } else { - Assert.NotEqual((IntPtr)(-1), result.bstrVal); - Assert.NotEqual(IntPtr.Zero, result.bstrVal); + Assert.NotEqual((IntPtr)(-1), result.GetRawDataRef()); + Assert.NotEqual(IntPtr.Zero, result.GetRawDataRef()); } // Make sure it roundtrips. @@ -141,24 +141,23 @@ public void GetNativeVariantForObject_ValidObject_Success(object primitive, VarE [InlineData("99")] public void GetNativeVariantForObject_String_Success(string obj) { - var v = new Variant(); - IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v)); + IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf()); try { Marshal.GetNativeVariantForObject(obj, pNative); - Variant result = Marshal.PtrToStructure(pNative); + ComVariant result = Marshal.PtrToStructure(pNative); try { - Assert.Equal(VarEnum.VT_BSTR, (VarEnum)result.vt); - Assert.Equal(obj, Marshal.PtrToStringBSTR(result.bstrVal)); + Assert.Equal(VarEnum.VT_BSTR, result.VarType); + Assert.Equal(obj, Marshal.PtrToStringBSTR(result.GetRawDataRef())); object o = Marshal.GetObjectForNativeVariant(pNative); Assert.Equal(obj, o); } finally { - Marshal.FreeBSTR(result.bstrVal); + Marshal.FreeBSTR(result.GetRawDataRef()); } } finally @@ -171,8 +170,7 @@ public void GetNativeVariantForObject_String_Success(string obj) public unsafe void GetNativeVariantForObject_Guid_Success() { var guid = new Guid("0DD3E51B-3162-4D13-B906-030F402C5BA2"); - var v = new Variant(); - IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v)); + IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf()); try { if (PlatformDetection.IsWindowsNanoServer) @@ -183,12 +181,12 @@ public unsafe void GetNativeVariantForObject_Guid_Success() { Marshal.GetNativeVariantForObject(guid, pNative); - Variant result = Marshal.PtrToStructure(pNative); - Assert.Equal(VarEnum.VT_RECORD, (VarEnum)result.vt); - Assert.NotEqual(nint.Zero, result.pRecInfo); // We should have an IRecordInfo instance. + ComVariant result = Marshal.PtrToStructure(pNative); + Assert.Equal(VarEnum.VT_RECORD, result.VarType); + Assert.NotEqual(nint.Zero, result.GetRawDataRef()._recordInfo); // We should have an IRecordInfo instance. var expectedBytes = new ReadOnlySpan(guid.ToByteArray()); - var actualBytes = new ReadOnlySpan((void*)result.bstrVal, expectedBytes.Length); + var actualBytes = new ReadOnlySpan((void*)result.GetRawDataRef()._record, expectedBytes.Length); Assert.Equal(expectedBytes, actualBytes); object o = Marshal.GetObjectForNativeVariant(pNative); @@ -205,15 +203,14 @@ public unsafe void GetNativeVariantForObject_Guid_Success() [InlineData(3.14)] public unsafe void GetNativeVariantForObject_Double_Success(double obj) { - var v = new Variant(); - IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v)); + IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf()); try { Marshal.GetNativeVariantForObject(obj, pNative); - Variant result = Marshal.PtrToStructure(pNative); - Assert.Equal(VarEnum.VT_R8, (VarEnum)result.vt); - Assert.Equal(*((ulong*)&obj), *((ulong*)&result.bstrVal)); + ComVariant result = Marshal.PtrToStructure(pNative); + Assert.Equal(VarEnum.VT_R8, result.VarType); + Assert.Equal(*((ulong*)&obj), result.GetRawDataRef()); object o = Marshal.GetObjectForNativeVariant(pNative); Assert.Equal(obj, o); @@ -228,15 +225,14 @@ public unsafe void GetNativeVariantForObject_Double_Success(double obj) [InlineData(3.14f)] public unsafe void GetNativeVariantForObject_Float_Success(float obj) { - var v = new Variant(); - IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v)); + IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf()); try { Marshal.GetNativeVariantForObject(obj, pNative); - Variant result = Marshal.PtrToStructure(pNative); - Assert.Equal(VarEnum.VT_R4, (VarEnum)result.vt); - Assert.Equal(*((uint*)&obj), *((uint*)&result.bstrVal)); + ComVariant result = Marshal.PtrToStructure(pNative); + Assert.Equal(VarEnum.VT_R4, result.VarType); + Assert.Equal(*((uint*)&obj), result.GetRawDataRef()); object o = Marshal.GetObjectForNativeVariant(pNative); Assert.Equal(obj, o); @@ -279,8 +275,7 @@ public void GetNativeVariantForObject_GenericObject_ThrowsArgumentException(obje [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltInComEnabled))] public void GetNativeVariant_InvalidArray_ThrowsSafeArrayTypeMismatchException() { - var v = new Variant(); - IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v)); + IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf()); try { Assert.Throws(() => Marshal.GetNativeVariantForObject(new int[][] { }, pNative)); @@ -302,8 +297,7 @@ public static IEnumerable GetNativeVariant_VariantWrapper_TestData() [MemberData(nameof(GetNativeVariant_VariantWrapper_TestData))] public void GetNativeVariant_VariantWrapper_ThrowsArgumentException(object obj) { - var v = new Variant(); - IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v)); + IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf()); try { AssertExtensions.Throws(null, () => Marshal.GetNativeVariantForObject(obj, pNative)); @@ -328,8 +322,7 @@ public static IEnumerable GetNativeVariant_HandleObject_TestData() [MemberData(nameof(GetNativeVariant_HandleObject_TestData))] public void GetNativeVariant_HandleObject_ThrowsArgumentException(object obj) { - var v = new Variant(); - IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v)); + IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf()); try { AssertExtensions.Throws(null, () => Marshal.GetNativeVariantForObject(obj, pNative)); @@ -346,8 +339,7 @@ public static void GetNativeVariantForObject_CantCastToObject_ThrowsInvalidCastE { // While GetNativeVariantForObject supports taking chars, GetObjectForNativeVariant will // never return a char. The internal type is ushort, as mentioned above. - var v = new Variant(); - IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v)); + IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf()); try { Marshal.GetNativeVariantForObject('a', pNative); @@ -372,6 +364,13 @@ public enum UInt16Enum : ushort { Value1, Value2 } public enum UInt32Enum : uint { Value1, Value2 } public enum UInt64Enum : ulong { Value1, Value2 } + [StructLayout(LayoutKind.Sequential)] + private struct Record + { + public nint _record; + public nint _recordInfo; + } + public class FakeSafeHandle : SafeHandle { public FakeSafeHandle() : base(IntPtr.Zero, false) { } From 176826630ec062d4b195a5b6549f94eaa3bf28cb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 28 Apr 2026 22:19:14 +0000 Subject: [PATCH 2/2] Use stack-local ComVariant in native variant test Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/c57d38e8-01e8-45b2-82b3-4c1b46f06ea4 Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com> --- .../Marshal/GetNativeVariantForObjectTests.cs | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetNativeVariantForObjectTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetNativeVariantForObjectTests.cs index af116064127e2d..5c0eac01f22750 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetNativeVariantForObjectTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetNativeVariantForObjectTests.cs @@ -108,31 +108,35 @@ public static IEnumerable GetNativeVariantForObject_NonRoundtrippingPr [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltInComEnabled))] [MemberData(nameof(GetNativeVariantForObject_NonRoundtrippingPrimitives_TestData))] - public void GetNativeVariantForObject_ValidObject_Success(object primitive, VarEnum expectedVarType, IntPtr expectedValue, object expectedRoundtripValue) + public unsafe void GetNativeVariantForObject_ValidObject_Success(object primitive, VarEnum expectedVarType, IntPtr expectedValue, object expectedRoundtripValue) { - IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf()); + ComVariant variant = default; + bool variantInitialized = false; try { - Marshal.GetNativeVariantForObject(primitive, pNative); + Marshal.GetNativeVariantForObject(primitive, (nint)(&variant)); + variantInitialized = true; - ComVariant result = Marshal.PtrToStructure(pNative); - Assert.Equal(expectedVarType, result.VarType); + Assert.Equal(expectedVarType, variant.VarType); if (expectedValue != (IntPtr)(-1)) { - Assert.Equal(expectedValue, result.GetRawDataRef()); + Assert.Equal(expectedValue, variant.GetRawDataRef()); } else { - Assert.NotEqual((IntPtr)(-1), result.GetRawDataRef()); - Assert.NotEqual(IntPtr.Zero, result.GetRawDataRef()); + Assert.NotEqual((IntPtr)(-1), variant.GetRawDataRef()); + Assert.NotEqual(IntPtr.Zero, variant.GetRawDataRef()); } // Make sure it roundtrips. - Assert.Equal(expectedRoundtripValue, Marshal.GetObjectForNativeVariant(pNative)); + Assert.Equal(expectedRoundtripValue, Marshal.GetObjectForNativeVariant((nint)(&variant))); } finally { - Marshal.FreeHGlobal(pNative); + if (variantInitialized) + { + variant.Dispose(); + } } }