diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs index 9221bef508f3b9..0a18241ef7c767 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs @@ -2,13 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; -using System.Linq; using System.Collections.Generic; using System.Collections.Immutable; +using System.Linq; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -using Microsoft.CodeAnalysis; namespace Microsoft.Interop.JavaScript { @@ -61,13 +61,13 @@ public BlockSyntax GenerateJSExportBody() { StatementSyntax invoke = InvokeSyntax(); GeneratedStatements statements = GeneratedStatements.Create(_marshallers, _context); - bool shouldInitializeVariables = !statements.GuaranteedUnmarshal.IsEmpty || !statements.Cleanup.IsEmpty; + bool shouldInitializeVariables = !statements.GuaranteedUnmarshal.IsEmpty || !statements.CleanupCallerAllocated.IsEmpty || !statements.CleanupCalleeAllocated.IsEmpty; VariableDeclarations declarations = VariableDeclarations.GenerateDeclarationsForUnmanagedToManaged(_marshallers, _context, shouldInitializeVariables); var setupStatements = new List(); SetupSyntax(setupStatements); - if (!statements.GuaranteedUnmarshal.IsEmpty) + if (!(statements.GuaranteedUnmarshal.IsEmpty && statements.CleanupCalleeAllocated.IsEmpty)) { setupStatements.Add(MarshallerHelpers.Declare(PredefinedType(Token(SyntaxKind.BoolKeyword)), InvokeSucceededIdentifier, initializeToDefault: true)); } @@ -81,7 +81,7 @@ public BlockSyntax GenerateJSExportBody() tryStatements.Add(invoke); - if (!statements.GuaranteedUnmarshal.IsEmpty) + if (!(statements.GuaranteedUnmarshal.IsEmpty && statements.CleanupCalleeAllocated.IsEmpty)) { tryStatements.Add(ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName(InvokeSucceededIdentifier), @@ -94,12 +94,12 @@ public BlockSyntax GenerateJSExportBody() List allStatements = setupStatements; List finallyStatements = new List(); - if (!statements.GuaranteedUnmarshal.IsEmpty) + if (!(statements.GuaranteedUnmarshal.IsEmpty && statements.CleanupCalleeAllocated.IsEmpty)) { - finallyStatements.Add(IfStatement(IdentifierName(InvokeSucceededIdentifier), Block(statements.GuaranteedUnmarshal))); + finallyStatements.Add(IfStatement(IdentifierName(InvokeSucceededIdentifier), Block(statements.GuaranteedUnmarshal.Concat(statements.CleanupCalleeAllocated)))); } - finallyStatements.AddRange(statements.Cleanup); + finallyStatements.AddRange(statements.CleanupCallerAllocated); if (finallyStatements.Count > 0) { allStatements.Add( diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportCodeGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportCodeGenerator.cs index 2c1d49fd3dd12e..1f415b8338008e 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportCodeGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportCodeGenerator.cs @@ -67,14 +67,14 @@ public BlockSyntax GenerateJSImportBody() { StatementSyntax invoke = InvokeSyntax(); GeneratedStatements statements = GeneratedStatements.Create(_marshallers, _context); - bool shouldInitializeVariables = !statements.GuaranteedUnmarshal.IsEmpty || !statements.Cleanup.IsEmpty; + bool shouldInitializeVariables = !statements.GuaranteedUnmarshal.IsEmpty || !statements.CleanupCallerAllocated.IsEmpty || !statements.CleanupCalleeAllocated.IsEmpty; VariableDeclarations declarations = VariableDeclarations.GenerateDeclarationsForManagedToUnmanaged(_marshallers, _context, shouldInitializeVariables); var setupStatements = new List(); BindSyntax(setupStatements); SetupSyntax(setupStatements); - if (!statements.GuaranteedUnmarshal.IsEmpty) + if (!(statements.GuaranteedUnmarshal.IsEmpty && statements.CleanupCalleeAllocated.IsEmpty)) { setupStatements.Add(MarshallerHelpers.Declare(PredefinedType(Token(SyntaxKind.BoolKeyword)), InvokeSucceededIdentifier, initializeToDefault: true)); } @@ -88,7 +88,7 @@ public BlockSyntax GenerateJSImportBody() tryStatements.AddRange(statements.PinnedMarshal); tryStatements.Add(invoke); - if (!statements.GuaranteedUnmarshal.IsEmpty) + if (!(statements.GuaranteedUnmarshal.IsEmpty && statements.CleanupCalleeAllocated.IsEmpty)) { tryStatements.Add(ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName(InvokeSucceededIdentifier), @@ -100,12 +100,12 @@ public BlockSyntax GenerateJSImportBody() List allStatements = setupStatements; List finallyStatements = new List(); - if (!statements.GuaranteedUnmarshal.IsEmpty) + if (!(statements.GuaranteedUnmarshal.IsEmpty && statements.CleanupCalleeAllocated.IsEmpty)) { - finallyStatements.Add(IfStatement(IdentifierName(InvokeSucceededIdentifier), Block(statements.GuaranteedUnmarshal))); + finallyStatements.Add(IfStatement(IdentifierName(InvokeSucceededIdentifier), Block(statements.GuaranteedUnmarshal.Concat(statements.CleanupCalleeAllocated)))); } - finallyStatements.AddRange(statements.Cleanup); + finallyStatements.AddRange(statements.CleanupCallerAllocated); if (finallyStatements.Count > 0) { // Add try-finally block if there are any statements in the finally block diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs index 883ca85161771f..dd18f01bb7c88b 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs @@ -131,7 +131,7 @@ public BlockSyntax GenerateStubBody(int index, ImmutableArray = true; - if (!statements.GuaranteedUnmarshal.IsEmpty) + if (!(statements.GuaranteedUnmarshal.IsEmpty && statements.CleanupCalleeAllocated.IsEmpty)) { tryStatements.Add(ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName(InvokeSucceededIdentifier), @@ -197,12 +197,12 @@ public BlockSyntax GenerateStubBody(int index, ImmutableArray allStatements = setupStatements; List finallyStatements = new List(); - if (!statements.GuaranteedUnmarshal.IsEmpty) + if (!(statements.GuaranteedUnmarshal.IsEmpty && statements.CleanupCalleeAllocated.IsEmpty)) { - finallyStatements.Add(IfStatement(IdentifierName(InvokeSucceededIdentifier), Block(statements.GuaranteedUnmarshal))); + finallyStatements.Add(IfStatement(IdentifierName(InvokeSucceededIdentifier), Block(statements.GuaranteedUnmarshal.Concat(statements.CleanupCalleeAllocated)))); } - finallyStatements.AddRange(statements.Cleanup); + finallyStatements.AddRange(statements.CleanupCallerAllocated); if (finallyStatements.Count > 0) { // Add try-finally block if there are any statements in the finally block diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/UnmanagedToManagedStubGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/UnmanagedToManagedStubGenerator.cs index 64060d613e429d..cc76d853e06bd9 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/UnmanagedToManagedStubGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/UnmanagedToManagedStubGenerator.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; @@ -52,9 +53,11 @@ public BlockSyntax GenerateStubBody(ExpressionSyntax methodToInvoke) _marshallers, _context, methodToInvoke); + Debug.Assert(statements.CleanupCalleeAllocated.IsEmpty); + bool shouldInitializeVariables = !statements.GuaranteedUnmarshal.IsEmpty - || !statements.Cleanup.IsEmpty + || !statements.CleanupCallerAllocated.IsEmpty || !statements.ManagedExceptionCatchClauses.IsEmpty; VariableDeclarations declarations = VariableDeclarations.GenerateDeclarationsForUnmanagedToManaged(_marshallers, _context, shouldInitializeVariables); @@ -77,7 +80,7 @@ public BlockSyntax GenerateStubBody(ExpressionSyntax methodToInvoke) SyntaxList catchClauses = List(statements.ManagedExceptionCatchClauses); - finallyStatements.AddRange(statements.Cleanup); + finallyStatements.AddRange(statements.CleanupCallerAllocated); if (finallyStatements.Count > 0) { allStatements.Add( diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/PInvokeStubCodeGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/PInvokeStubCodeGenerator.cs index 34d09a70a66e6f..939a623ab7dba8 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/PInvokeStubCodeGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/PInvokeStubCodeGenerator.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Linq; using System.Collections.Generic; using System.Collections.Immutable; using Microsoft.CodeAnalysis.CSharp; @@ -107,7 +108,7 @@ public PInvokeStubCodeGenerator( public BlockSyntax GeneratePInvokeBody(string dllImportName) { GeneratedStatements statements = GeneratedStatements.Create(_marshallers, _context, IdentifierName(dllImportName)); - bool shouldInitializeVariables = !statements.GuaranteedUnmarshal.IsEmpty || !statements.Cleanup.IsEmpty; + bool shouldInitializeVariables = !statements.GuaranteedUnmarshal.IsEmpty || !statements.CleanupCallerAllocated.IsEmpty || !statements.CleanupCalleeAllocated.IsEmpty; VariableDeclarations declarations = VariableDeclarations.GenerateDeclarationsForManagedToUnmanaged(_marshallers, _context, shouldInitializeVariables); var setupStatements = new List(); @@ -121,7 +122,7 @@ public BlockSyntax GeneratePInvokeBody(string dllImportName) initializeToDefault: false)); } - if (!statements.GuaranteedUnmarshal.IsEmpty) + if (!(statements.GuaranteedUnmarshal.IsEmpty && statements.CleanupCalleeAllocated.IsEmpty)) { setupStatements.Add(MarshallerHelpers.Declare(PredefinedType(Token(SyntaxKind.BoolKeyword)), InvokeSucceededIdentifier, initializeToDefault: true)); } @@ -148,7 +149,7 @@ public BlockSyntax GeneratePInvokeBody(string dllImportName) } tryStatements.Add(statements.Pin.NestFixedStatements(fixedBlock)); // = true; - if (!statements.GuaranteedUnmarshal.IsEmpty) + if (!(statements.GuaranteedUnmarshal.IsEmpty && statements.CleanupCalleeAllocated.IsEmpty)) { tryStatements.Add(ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName(InvokeSucceededIdentifier), @@ -160,12 +161,12 @@ public BlockSyntax GeneratePInvokeBody(string dllImportName) List allStatements = setupStatements; List finallyStatements = new List(); - if (!statements.GuaranteedUnmarshal.IsEmpty) + if (!(statements.GuaranteedUnmarshal.IsEmpty && statements.CleanupCalleeAllocated.IsEmpty)) { - finallyStatements.Add(IfStatement(IdentifierName(InvokeSucceededIdentifier), Block(statements.GuaranteedUnmarshal))); + finallyStatements.Add(IfStatement(IdentifierName(InvokeSucceededIdentifier), Block(statements.GuaranteedUnmarshal.Concat(statements.CleanupCalleeAllocated)))); } - finallyStatements.AddRange(statements.Cleanup); + finallyStatements.AddRange(statements.CleanupCallerAllocated); if (finallyStatements.Count > 0) { // Add try-finally block if there are any statements in the finally block diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/GeneratedStatements.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/GeneratedStatements.cs index e8e3de05ffff27..d611eb59cd3b40 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/GeneratedStatements.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/GeneratedStatements.cs @@ -21,7 +21,8 @@ public struct GeneratedStatements public ImmutableArray Unmarshal { get; init; } public ImmutableArray NotifyForSuccessfulInvoke { get; init; } public ImmutableArray GuaranteedUnmarshal { get; init; } - public ImmutableArray Cleanup { get; init; } + public ImmutableArray CleanupCallerAllocated { get; init; } + public ImmutableArray CleanupCalleeAllocated { get; init; } public ImmutableArray ManagedExceptionCatchClauses { get; init; } @@ -38,7 +39,8 @@ public static GeneratedStatements Create(BoundGenerators marshallers, StubCodeCo .AddRange(GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.Unmarshal })), NotifyForSuccessfulInvoke = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.NotifyForSuccessfulInvoke }), GuaranteedUnmarshal = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.GuaranteedUnmarshal }), - Cleanup = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.Cleanup }), + CleanupCallerAllocated = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.CleanupCallerAllocated }), + CleanupCalleeAllocated = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.CleanupCalleeAllocated }), ManagedExceptionCatchClauses = GenerateCatchClauseForManagedException(marshallers, context) }; } @@ -182,7 +184,8 @@ private static SyntaxTriviaList GenerateStageTrivia(StubCodeContext.Stage stage) StubCodeContext.Stage.Invoke => "Call the P/Invoke.", StubCodeContext.Stage.UnmarshalCapture => "Capture the native data into marshaller instances in case conversion to managed data throws an exception.", StubCodeContext.Stage.Unmarshal => "Convert native data to managed data.", - StubCodeContext.Stage.Cleanup => "Perform required cleanup.", + StubCodeContext.Stage.CleanupCallerAllocated => "Perform cleanup of caller allocated resources.", + StubCodeContext.Stage.CleanupCalleeAllocated => "Perform cleanup of callee allocated resources.", StubCodeContext.Stage.NotifyForSuccessfulInvoke => "Keep alive any managed objects that need to stay alive across the call.", StubCodeContext.Stage.GuaranteedUnmarshal => "Convert native data to managed data even in the case of an exception during the non-cleanup phases.", _ => throw new ArgumentOutOfRangeException(nameof(stage)) diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CustomTypeMarshallingGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CustomTypeMarshallingGenerator.cs index 7873781e475df4..8d7360b507438e 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CustomTypeMarshallingGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CustomTypeMarshallingGenerator.cs @@ -97,7 +97,9 @@ public IEnumerable Generate(TypePositionInfo info, StubCodeCont return _nativeTypeMarshaller.GenerateGuaranteedUnmarshalStatements(info, context); } break; - case StubCodeContext.Stage.Cleanup: + case StubCodeContext.Stage.CleanupCallerAllocated when GetCleanupStage(info, context) is StubCodeContext.Stage.CleanupCallerAllocated: + return _nativeTypeMarshaller.GenerateCleanupStatements(info, context); + case StubCodeContext.Stage.CleanupCalleeAllocated when GetCleanupStage(info, context) is StubCodeContext.Stage.CleanupCalleeAllocated: return _nativeTypeMarshaller.GenerateCleanupStatements(info, context); default: break; @@ -115,6 +117,20 @@ private bool ShouldGenerateByValueOutMarshalling(TypePositionInfo info, StubCode && !_isPinned; } + /// + /// Returns which stage cleanup should be performed for the parameter. + /// + private static StubCodeContext.Stage GetCleanupStage(TypePositionInfo info, StubCodeContext context) + { + if (context.Direction is MarshalDirection.UnmanagedToManaged) + return StubCodeContext.Stage.CleanupCallerAllocated; + + if (MarshallerHelpers.GetMarshalDirection(info, context) is MarshalDirection.UnmanagedToManaged) + return StubCodeContext.Stage.CleanupCalleeAllocated; + + return StubCodeContext.Stage.CleanupCallerAllocated; + } + public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) { return _nativeTypeMarshaller.UsesNativeIdentifier(info, context); diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ElementsMarshalling.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ElementsMarshalling.cs index 55818927c3965b..d9ac5a9442ef13 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ElementsMarshalling.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ElementsMarshalling.cs @@ -440,7 +440,8 @@ public override StatementSyntax GenerateElementCleanupStatement(TypePositionInfo indexConstraintName, _elementInfo, _elementMarshaller, - StubCodeContext.Stage.Cleanup); + StubCodeContext.Stage.CleanupCallerAllocated, + StubCodeContext.Stage.CleanupCalleeAllocated); if (contentsCleanupStatements.IsKind(SyntaxKind.EmptyStatement)) { @@ -543,7 +544,8 @@ public override StatementSyntax GenerateUnmanagedToManagedByValueOutMarshalState new FreeAlwaysOwnedOriginalValueGenerator(_elementMarshaller), StubCodeContext.Stage.Marshal, StubCodeContext.Stage.PinnedMarshal, - StubCodeContext.Stage.Cleanup)); + StubCodeContext.Stage.CleanupCallerAllocated, + StubCodeContext.Stage.CleanupCalleeAllocated)); } private static List GenerateElementStages( diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/SafeHandleMarshaller.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/SafeHandleMarshaller.cs index 4e0b3bcf40f922..9f4700ec00f936 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/SafeHandleMarshaller.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/SafeHandleMarshaller.cs @@ -214,7 +214,7 @@ public IEnumerable Generate(TypePositionInfo info, StubCodeCont IdentifierName(newHandleObjectIdentifier))))); } break; - case StubCodeContext.Stage.Cleanup: + case StubCodeContext.Stage.CleanupCallerAllocated: if (!info.IsManagedReturnPosition && (!info.IsByRef || info.RefKind == RefKind.In)) { yield return IfStatement( diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/UnmanagedToManagedOwnershipTrackingStrategy.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/UnmanagedToManagedOwnershipTrackingStrategy.cs index 5b9d0866f743cd..c6b5c7685b027b 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/UnmanagedToManagedOwnershipTrackingStrategy.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/UnmanagedToManagedOwnershipTrackingStrategy.cs @@ -78,7 +78,7 @@ public IEnumerable GenerateSetupStatements(TypePositionInfo inf /// /// Marshalling strategy that uses the tracking variables introduced by to cleanup the original value if the original value is owned - /// in the stage. + /// in the stage. /// internal sealed class CleanupOwnedOriginalValueMarshalling : ICustomTypeMarshallingStrategy { @@ -119,7 +119,7 @@ public IEnumerable GenerateCleanupStatements(TypePositionInfo i /// /// Marshalling strategy to cache the initial value of a given in a local variable and cleanup that value in the cleanup stage. - /// Useful in scenarios where the value is always owned in all code-paths that reach the stage, so additional ownership tracking is extraneous. + /// Useful in scenarios where the value is always owned in all code-paths that reach the stage, so additional ownership tracking is extraneous. /// internal sealed class FreeAlwaysOwnedOriginalValueGenerator : IMarshallingGenerator { @@ -138,7 +138,7 @@ public IEnumerable Generate(TypePositionInfo info, StubCodeCont return GenerateSetupStatements(); } - if (context.CurrentStage == StubCodeContext.Stage.Cleanup) + if (context.CurrentStage == StubCodeContext.Stage.CleanupCallerAllocated) { return GenerateStatementsFromInner(new OwnedValueCodeContext(context)); } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/StubCodeContext.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/StubCodeContext.cs index 35e07f1f7dc477..50af716eb3a51f 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/StubCodeContext.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/StubCodeContext.cs @@ -64,9 +64,14 @@ public enum Stage NotifyForSuccessfulInvoke, /// - /// Perform any cleanup required + /// Perform any cleanup required on caller allocated resources /// - Cleanup, + CleanupCallerAllocated, + + /// + /// Perform any cleanup required on callee allocated resources + /// + CleanupCalleeAllocated, /// /// Convert native data to managed data even in the case of an exception during diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/RcwAroundCcwTests.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/RcwAroundCcwTests.cs index 75e95251e91bf1..b4d0d0a86d3335 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/RcwAroundCcwTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/RcwAroundCcwTests.cs @@ -145,35 +145,36 @@ public void IStatelessFinallyMarshalling() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/89747")] public void ICollectionMarshallingFails() { + Type hrExceptionType = SystemFindsComCalleeException() ? typeof(MarshallingFailureException) : typeof(Exception); + var obj = CreateWrapper(); Assert.Throws(() => - _ = obj.GetConstSize() + obj.Set(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }, 10) ); - Assert.Throws(() => - _ = obj.Get(out _) + Assert.Throws(hrExceptionType, () => + _ = obj.GetConstSize() ); - Assert.Throws(() => - obj.Set(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }, 10) + Assert.Throws(hrExceptionType, () => + _ = obj.Get(out _) ); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/89747")] public void IJaggedArrayMarshallingFails() { + Type hrExceptionType = SystemFindsComCalleeException() ? typeof(MarshallingFailureException) : typeof(Exception); var obj = CreateWrapper(); - Assert.Throws(() => + Assert.Throws(hrExceptionType, () => _ = obj.GetConstSize() ); - Assert.Throws(() => + Assert.Throws(hrExceptionType, () => _ = obj.Get(out _, out _) ); var array = new int[][] { new int[] { 1, 2, 3 }, new int[] { 4, 5, }, new int[] { 6, 7, 8, 9 } };