diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs
index 5acdc3072a225b..ec05c0d3dcb077 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs
@@ -4,6 +4,7 @@
 using System;
 using System.Collections.Generic;
 using System.Collections.Immutable;
+using System.Diagnostics;
 using System.Linq;
 using Microsoft.CodeAnalysis;
 using Microsoft.CodeAnalysis.CSharp;
@@ -220,6 +221,9 @@ public BlockSyntax GenerateStubBody(int index, ImmutableArray<FunctionPointerUnm
                 allStatements.Add(MarshallerHelpers.CreateSetLastPInvokeErrorStatement(LastErrorIdentifier));
             }
 
+            // ManagedToUnmanaged shouldn't need AssignOut stage
+            Debug.Assert(statements.AssignOut.IsEmpty);
+
             // Return
             if (!_marshallers.IsManagedVoidReturn)
                 allStatements.Add(ReturnStatement(IdentifierName(_context.GetIdentifiers(_marshallers.ManagedReturnMarshaller.TypeInfo).managed)));
diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Marshallers/ComInterfaceDispatchMarshallerFactory.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Marshallers/ComInterfaceDispatchMarshallerFactory.cs
index 15a3ce6533cb47..134d1f837c438a 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Marshallers/ComInterfaceDispatchMarshallerFactory.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Marshallers/ComInterfaceDispatchMarshallerFactory.cs
@@ -3,6 +3,7 @@
 
 using System;
 using System.Collections.Generic;
+using System.Diagnostics;
 using Microsoft.CodeAnalysis.CSharp;
 using Microsoft.CodeAnalysis.CSharp.Syntax;
 using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
@@ -34,27 +35,32 @@ public ManagedTypeInfo AsNativeType(TypePositionInfo info) =>
                     IsFunctionPointer: false);
             public IEnumerable<StatementSyntax> Generate(TypePositionInfo info, StubCodeContext context)
             {
-                if (context.CurrentStage != StubCodeContext.Stage.Unmarshal)
+                switch (context.CurrentStage)
                 {
-                    yield break;
+                    case StubCodeContext.Stage.Unmarshal:
+                        var (managed, native) = context.GetIdentifiers(info);
+                        // <managed> = ComWrappers.ComInterfaceDispatch.GetInstance<<managedType>>(<native>);
+                        yield return ExpressionStatement(
+                            AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
+                                IdentifierName(managed),
+                                InvocationExpression(
+                                    MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
+                                        ParseName(TypeNames.System_Runtime_InteropServices_ComWrappers_ComInterfaceDispatch),
+                                        GenericName(
+                                            Identifier("GetInstance"),
+                                            TypeArgumentList(SingletonSeparatedList(info.ManagedType.Syntax)))),
+                                    ArgumentList(
+                                        SingletonSeparatedList(
+                                            Argument(
+                                                IdentifierName(native)))))));
+                        yield break;
+                    case StubCodeContext.Stage.AssignOut:
+                        Debug.Assert(MarshallerHelpers.MarshalsOut(info, context));
+                        yield return this.GeneratePointerAssignOut(info, context);
+                        yield break;
+                    default:
+                        yield break;
                 }
-
-                var (managed, native) = context.GetIdentifiers(info);
-
-                // <managed> = ComWrappers.ComInterfaceDispatch.GetInstance<<managedType>>(<native>);
-                yield return ExpressionStatement(
-                    AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
-                        IdentifierName(managed),
-                        InvocationExpression(
-                            MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
-                                ParseName(TypeNames.System_Runtime_InteropServices_ComWrappers_ComInterfaceDispatch),
-                                GenericName(
-                                    Identifier("GetInstance"),
-                                    TypeArgumentList(SingletonSeparatedList(info.ManagedType.Syntax)))),
-                            ArgumentList(
-                                SingletonSeparatedList(
-                                    Argument(
-                                        IdentifierName(native)))))));
             }
 
             public SignatureBehavior GetNativeSignatureBehavior(TypePositionInfo info) => SignatureBehavior.NativeType;
diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/UnmanagedToManagedStubGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/UnmanagedToManagedStubGenerator.cs
index 6d255912aedaab..16a325c6eb39bd 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/UnmanagedToManagedStubGenerator.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/UnmanagedToManagedStubGenerator.cs
@@ -5,7 +5,6 @@
 using System.Collections.Generic;
 using System.Collections.Immutable;
 using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
 using Microsoft.CodeAnalysis.CSharp.Syntax;
 using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
 
@@ -14,7 +13,6 @@ namespace Microsoft.Interop
     internal sealed class UnmanagedToManagedStubGenerator
     {
         private const string ReturnIdentifier = "__retVal";
-        private const string InvokeSucceededIdentifier = "__invokeSucceeded";
 
         private readonly BoundGenerators _marshallers;
 
@@ -60,41 +58,28 @@ public BlockSyntax GenerateStubBody(ExpressionSyntax methodToInvoke)
                 || !statements.ManagedExceptionCatchClauses.IsEmpty;
             VariableDeclarations declarations = VariableDeclarations.GenerateDeclarationsForUnmanagedToManaged(_marshallers, _context, shouldInitializeVariables);
 
-            if (!statements.GuaranteedUnmarshal.IsEmpty)
-            {
-                setupStatements.Add(MarshallerHelpers.Declare(PredefinedType(Token(SyntaxKind.BoolKeyword)), InvokeSucceededIdentifier, initializeToDefault: true));
-            }
-
-            setupStatements.AddRange(declarations.Initializations);
             setupStatements.AddRange(declarations.Variables);
+            setupStatements.AddRange(declarations.Initializations);
             setupStatements.AddRange(statements.Setup);
 
             List<StatementSyntax> tryStatements = new();
             tryStatements.AddRange(statements.Unmarshal);
+            tryStatements.AddRange(statements.GuaranteedUnmarshal);
 
             tryStatements.Add(statements.InvokeStatement);
 
-            if (!statements.GuaranteedUnmarshal.IsEmpty)
-            {
-                tryStatements.Add(ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
-                    IdentifierName(InvokeSucceededIdentifier),
-                    LiteralExpression(SyntaxKind.TrueLiteralExpression))));
-            }
-
             tryStatements.AddRange(statements.NotifyForSuccessfulInvoke);
-            tryStatements.AddRange(statements.PinnedMarshal);
             tryStatements.AddRange(statements.Marshal);
+            tryStatements.AddRange(statements.PinnedMarshal);
+
+            tryStatements.AddRange(statements.AssignOut);
+            tryStatements.AddRange(statements.Cleanup);
 
             List<StatementSyntax> allStatements = setupStatements;
             List<StatementSyntax> finallyStatements = new();
-            if (!statements.GuaranteedUnmarshal.IsEmpty)
-            {
-                finallyStatements.Add(IfStatement(IdentifierName(InvokeSucceededIdentifier), Block(statements.GuaranteedUnmarshal)));
-            }
 
             SyntaxList<CatchClauseSyntax> catchClauses = List(statements.ManagedExceptionCatchClauses);
 
-            finallyStatements.AddRange(statements.Cleanup);
             if (finallyStatements.Count > 0)
             {
                 allStatements.Add(
@@ -110,6 +95,7 @@ public BlockSyntax GenerateStubBody(ExpressionSyntax methodToInvoke)
                 allStatements.AddRange(tryStatements);
             }
 
+
             // Return
             if (!_marshallers.IsUnmanagedVoidReturn)
                 allStatements.Add(ReturnStatement(IdentifierName(_context.GetIdentifiers(_marshallers.NativeReturnMarshaller.TypeInfo).native)));
diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/PInvokeStubCodeGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/PInvokeStubCodeGenerator.cs
index 34d09a70a66e6f..c843c797376eed 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/PInvokeStubCodeGenerator.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/PInvokeStubCodeGenerator.cs
@@ -4,6 +4,7 @@
 using System;
 using System.Collections.Generic;
 using System.Collections.Immutable;
+using System.Diagnostics;
 using Microsoft.CodeAnalysis.CSharp;
 using Microsoft.CodeAnalysis.CSharp.Syntax;
 using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
@@ -183,6 +184,9 @@ public BlockSyntax GeneratePInvokeBody(string dllImportName)
                 allStatements.Add(MarshallerHelpers.CreateSetLastPInvokeErrorStatement(LastErrorIdentifier));
             }
 
+            // ManagedToUnmanaged shouldn't need AssignOut stage
+            Debug.Assert(statements.AssignOut.IsEmpty);
+
             // Return
             if (!_marshallers.IsManagedVoidReturn)
                 allStatements.Add(ReturnStatement(IdentifierName(_context.GetIdentifiers(_marshallers.ManagedReturnMarshaller.TypeInfo).managed)));
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/BooleanMarshallingInfoProvider.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/BooleanMarshallingInfoProvider.cs
index 6a7b78acf1dd56..da0ea28c1aba15 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/BooleanMarshallingInfoProvider.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/BooleanMarshallingInfoProvider.cs
@@ -1,9 +1,6 @@
 ﻿// Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
-using System;
-using System.Collections.Generic;
-using System.Text;
 using Microsoft.CodeAnalysis;
 
 namespace Microsoft.Interop
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..d0fdf2883a4a81 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
@@ -22,7 +22,7 @@ public struct GeneratedStatements
         public ImmutableArray<StatementSyntax> NotifyForSuccessfulInvoke { get; init; }
         public ImmutableArray<StatementSyntax> GuaranteedUnmarshal { get; init; }
         public ImmutableArray<StatementSyntax> Cleanup { get; init; }
-
+        public ImmutableArray<StatementSyntax> AssignOut { get; init; }
         public ImmutableArray<CatchClauseSyntax> ManagedExceptionCatchClauses { get; init; }
 
         public static GeneratedStatements Create(BoundGenerators marshallers, StubCodeContext context)
@@ -39,7 +39,8 @@ public static GeneratedStatements Create(BoundGenerators marshallers, StubCodeCo
                 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 }),
-                ManagedExceptionCatchClauses = GenerateCatchClauseForManagedException(marshallers, context)
+                ManagedExceptionCatchClauses = GenerateCatchClauseForManagedException(marshallers, context),
+                AssignOut = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.AssignOut }),
             };
         }
         public static GeneratedStatements Create(BoundGenerators marshallers, StubCodeContext context, ExpressionSyntax expressionToInvoke)
@@ -71,7 +72,26 @@ private static ImmutableArray<StatementSyntax> GenerateStatementsForStubContext(
             ImmutableArray<StatementSyntax>.Builder statementsToUpdate = ImmutableArray.CreateBuilder<StatementSyntax>();
             foreach (BoundGenerator marshaller in marshallers.SignatureMarshallers)
             {
-                statementsToUpdate.AddRange(marshaller.Generator.Generate(marshaller.TypeInfo, context));
+                StubCodeContext localContext = context;
+                // Modify the context if we need to marshal out
+                switch (context.CurrentStage)
+                {
+                    case StubCodeContext.Stage.Marshal:
+                    case StubCodeContext.Stage.PinnedMarshal:
+                        if (MarshallerHelpers.MarshalsOut(marshaller.TypeInfo, context))
+                            localContext = new MarshalOutContext(context);
+                        break;
+                    case StubCodeContext.Stage.AssignOut:
+                        if (!MarshallerHelpers.MarshalsOut(marshaller.TypeInfo, context))
+                            continue;
+                        localContext = new AssignOutContext(context, marshaller.Generator.AsParameter(marshaller.TypeInfo, context).Identifier.ToString());
+                        break;
+                    case StubCodeContext.Stage.CleanupFailure:
+                        if (!MarshallerHelpers.MarshalsOut(marshaller.TypeInfo, context))
+                            continue;
+                        break;
+                }
+                statementsToUpdate.AddRange(marshaller.Generator.Generate(marshaller.TypeInfo, localContext));
             }
 
             if (statementsToUpdate.Count > 0)
@@ -150,7 +170,10 @@ private static ImmutableArray<CatchClauseSyntax> GenerateCatchClauseForManagedEx
         {
             if (!marshallers.HasManagedExceptionMarshaller)
             {
-                return ImmutableArray<CatchClauseSyntax>.Empty;
+                ImmutableArray.Create(CatchClause(
+                    CatchDeclaration(ParseTypeName(TypeNames.System_Exception)),
+                filter: null,
+                Block(List(GenerateStatementsForStubContext(marshallers, new MarshalOutContext(context with { CurrentStage = StubCodeContext.Stage.CleanupFailure }))))));
             }
             ImmutableArray<StatementSyntax>.Builder catchClauseBuilder = ImmutableArray.CreateBuilder<StatementSyntax>();
 
@@ -164,6 +187,15 @@ private static ImmutableArray<CatchClauseSyntax> GenerateCatchClauseForManagedEx
             catchClauseBuilder.AddRange(
                 managedExceptionMarshaller.Generator.Generate(
                     managedExceptionMarshaller.TypeInfo, context with { CurrentStage = StubCodeContext.Stage.PinnedMarshal }));
+            catchClauseBuilder.AddRange(GenerateStatementsForStubContext(marshallers, new MarshalOutContext(context with { CurrentStage = StubCodeContext.Stage.CleanupFailure })));
+            if (!marshallers.IsUnmanagedVoidReturn)
+            {
+                catchClauseBuilder.Add(ReturnStatement(IdentifierName(context.GetIdentifiers(marshallers.NativeReturnMarshaller.TypeInfo).native)));
+            }
+            else
+            {
+                catchClauseBuilder.Add(ReturnStatement());
+            }
             return ImmutableArray.Create(
                 CatchClause(
                     CatchDeclaration(ParseTypeName(TypeNames.System_Exception), Identifier(managed)),
@@ -183,8 +215,10 @@ private static SyntaxTriviaList GenerateStageTrivia(StubCodeContext.Stage stage)
                 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.CleanupFailure => "Perform required cleanup.",
                 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.",
+                StubCodeContext.Stage.AssignOut => "Assign to parameters",
                 _ => throw new ArgumentOutOfRangeException(nameof(stage))
             };
 
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AssignOutContext.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AssignOutContext.cs
new file mode 100644
index 00000000000000..e9b75d53fb5087
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AssignOutContext.cs
@@ -0,0 +1,35 @@
+﻿// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Diagnostics;
+
+namespace Microsoft.Interop
+{
+    public sealed record AssignOutContext : StubCodeContext
+    {
+        internal StubCodeContext InnerContext { get; init; }
+        public string ParameterIdentifier { get; init; }
+
+        internal AssignOutContext(StubCodeContext inner, string parameterIdentifier)
+        {
+            InnerContext = inner;
+            Debug.Assert(inner.CurrentStage == Stage.AssignOut);
+            CurrentStage = Stage.AssignOut;
+            Direction = inner.Direction;
+            ParentContext = inner.ParentContext;
+            ParameterIdentifier = parameterIdentifier;
+        }
+
+        public override (TargetFramework framework, Version version) GetTargetFramework() => InnerContext.GetTargetFramework();
+
+        public override bool SingleFrameSpansNativeContext => InnerContext.SingleFrameSpansNativeContext;
+
+        public override bool AdditionalTemporaryStateLivesAcrossStages => InnerContext.AdditionalTemporaryStateLivesAcrossStages;
+
+        public override (string managed, string native) GetIdentifiers(TypePositionInfo info)
+            => (InnerContext.GetIdentifiers(info).managed, InnerContext.GetAdditionalIdentifier(info, "out"));
+
+        public override string GetAdditionalIdentifier(TypePositionInfo info, string name) => InnerContext.GetAdditionalIdentifier(info, name);
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs
index 73b8cd8eb901a9..e503fbdaaa2dec 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs
@@ -278,20 +278,10 @@ private ResolvedGenerator CreateCustomNativeTypeMarshaller(TypePositionInfo info
 
                 FreeStrategy freeStrategy = GetFreeStrategy(info, context);
 
-                if (freeStrategy == FreeStrategy.FreeOriginal)
-                {
-                    marshallingStrategy = new UnmanagedToManagedOwnershipTrackingStrategy(marshallingStrategy);
-                }
-
-                if (freeStrategy != FreeStrategy.NoFree && marshallerData.Shape.HasFlag(MarshallerShape.Free))
+                if ((freeStrategy != FreeStrategy.NoFree) && marshallerData.Shape.HasFlag(MarshallerShape.Free))
                 {
                     marshallingStrategy = new StatelessFreeMarshalling(marshallingStrategy, marshallerData.MarshallerType.Syntax);
                 }
-
-                if (freeStrategy == FreeStrategy.FreeOriginal)
-                {
-                    marshallingStrategy = new CleanupOwnedOriginalValueMarshalling(marshallingStrategy);
-                }
             }
 
             IMarshallingGenerator marshallingGenerator = new CustomTypeMarshallingGenerator(marshallingStrategy, ByValueMarshalKindSupportDescriptor.Default, marshallerData.Shape.HasFlag(MarshallerShape.StatelessPinnableReference));
@@ -373,17 +363,7 @@ private ResolvedGenerator CreateNativeCollectionMarshaller(
                 IElementsMarshallingCollectionSource collectionSource = new StatefulLinearCollectionSource();
                 ElementsMarshalling elementsMarshalling = CreateElementsMarshalling(marshallerData, elementInfo, elementMarshaller, unmanagedElementType, collectionSource);
 
-                if (freeStrategy == FreeStrategy.FreeOriginal)
-                {
-                    marshallingStrategy = new UnmanagedToManagedOwnershipTrackingStrategy(marshallingStrategy);
-                }
-
-                marshallingStrategy = new StatefulLinearCollectionMarshalling(marshallingStrategy, marshallerData.Shape, numElementsExpression, elementsMarshalling, freeStrategy != FreeStrategy.NoFree);
-
-                if (freeStrategy == FreeStrategy.FreeOriginal)
-                {
-                    marshallingStrategy = new CleanupOwnedOriginalValueMarshalling(marshallingStrategy);
-                }
+                marshallingStrategy = new StatefulLinearCollectionMarshalling(marshallingStrategy, marshallerData.Shape, numElementsExpression, elementsMarshalling, nativeType.Syntax, freeStrategy is not FreeStrategy.NoFree);
 
                 if (marshallerData.Shape.HasFlag(MarshallerShape.Free))
                 {
@@ -397,14 +377,10 @@ private ResolvedGenerator CreateNativeCollectionMarshaller(
                 var freeStrategy = GetFreeStrategy(info, context);
 
                 IElementsMarshallingCollectionSource collectionSource = new StatelessLinearCollectionSource(marshallerTypeSyntax);
-                if (freeStrategy == FreeStrategy.FreeOriginal)
-                {
-                    marshallingStrategy = new UnmanagedToManagedOwnershipTrackingStrategy(marshallingStrategy);
-                }
 
                 ElementsMarshalling elementsMarshalling = CreateElementsMarshalling(marshallerData, elementInfo, elementMarshaller, unmanagedElementType, collectionSource);
 
-                marshallingStrategy = new StatelessLinearCollectionMarshalling(marshallingStrategy, elementsMarshalling, nativeType, marshallerData.Shape, numElementsExpression, freeStrategy != FreeStrategy.NoFree);
+                marshallingStrategy = new StatelessLinearCollectionMarshalling(marshallingStrategy, elementsMarshalling, nativeType, marshallerData.Shape, numElementsExpression, freeStrategy is not FreeStrategy.NoFree);
 
                 if (marshallerData.Shape.HasFlag(MarshallerShape.CallerAllocatedBuffer))
                 {
@@ -415,15 +391,10 @@ private ResolvedGenerator CreateNativeCollectionMarshaller(
                     marshallingStrategy = new StatelessCallerAllocatedBufferMarshalling(marshallingStrategy, marshallerTypeSyntax, bufferElementTypeSyntax, isLinearCollectionMarshalling: true);
                 }
 
-                if (freeStrategy != FreeStrategy.NoFree && marshallerData.Shape.HasFlag(MarshallerShape.Free))
+                if ((freeStrategy != FreeStrategy.NoFree) && marshallerData.Shape.HasFlag(MarshallerShape.Free))
                 {
                     marshallingStrategy = new StatelessFreeMarshalling(marshallingStrategy, marshallerTypeSyntax);
                 }
-
-                if (freeStrategy == FreeStrategy.FreeOriginal)
-                {
-                    marshallingStrategy = new CleanupOwnedOriginalValueMarshalling(marshallingStrategy);
-                }
             }
 
             ByValueMarshalKindSupportDescriptor byValueMarshalKindSupport;
@@ -467,7 +438,11 @@ private enum FreeStrategy
             /// <summary>
             /// Do not free the unmanaged value, we don't own it.
             /// </summary>
-            NoFree
+            NoFree,
+            /// <summary>
+            /// Free the unmanaged value if the unmanaged to managed stub throws before returning.
+            /// </summary>
+            FreeNativeOnFailure
         }
 
         private static FreeStrategy GetFreeStrategy(TypePositionInfo info, StubCodeContext context)
@@ -492,6 +467,13 @@ private static FreeStrategy GetFreeStrategy(TypePositionInfo info, StubCodeConte
                 return FreeStrategy.FreeOriginal;
             }
 
+            // If we marshal a value out to a native callee, we should free the marshalled value if we throw before returning
+            // ByValueContents Out we should not free the native identifier itself since we don't allocate a new one, only new elements
+            if (MarshallerHelpers.MarshalsOut(info, context) && !info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out))
+            {
+                return FreeStrategy.FreeNativeOnFailure;
+            }
+
             // In an unmanaged-to-managed stub, we don't take ownership of the value when it isn't passed by 'ref'.
             return FreeStrategy.NoFree;
         }
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BlittableMarshaller.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BlittableMarshaller.cs
index ef2542dd87bc8c..e5ed8343c4cc4a 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BlittableMarshaller.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BlittableMarshaller.cs
@@ -91,6 +91,9 @@ public IEnumerable<StatementSyntax> Generate(TypePositionInfo info, StubCodeCont
                                 IdentifierName(nativeIdentifier)));
                     }
                     break;
+                case StubCodeContext.Stage.AssignOut:
+                    yield return this.GeneratePointerAssignOut(info, context);
+                    break;
                 default:
                     break;
             }
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BoolMarshaller.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BoolMarshaller.cs
index a86df409e84a70..01b7bb1de87785 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BoolMarshaller.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BoolMarshaller.cs
@@ -92,6 +92,9 @@ public IEnumerable<StatementSyntax> Generate(TypePositionInfo info, StubCodeCont
                                     LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(comparand)))));
                     }
                     break;
+                case StubCodeContext.Stage.AssignOut:
+                    yield return this.GeneratePointerAssignOut(info, context);
+                    break;
                 default:
                     break;
             }
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CharMarshaller.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CharMarshaller.cs
index ecf0380219021d..d881cfa3f94343 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CharMarshaller.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CharMarshaller.cs
@@ -120,6 +120,9 @@ public IEnumerable<StatementSyntax> Generate(TypePositionInfo info, StubCodeCont
                                     IdentifierName(nativeIdentifier))));
                     }
 
+                    break;
+                case StubCodeContext.Stage.AssignOut:
+                    this.GeneratePointerAssignOut(info, context);
                     break;
                 default:
                     break;
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..548431f6fe3786 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
@@ -3,6 +3,8 @@
 
 using System;
 using System.Collections.Generic;
+using System.Diagnostics;
+using Microsoft.CodeAnalysis;
 using Microsoft.CodeAnalysis.CSharp.Syntax;
 
 namespace Microsoft.Interop
@@ -97,8 +99,13 @@ public IEnumerable<StatementSyntax> Generate(TypePositionInfo info, StubCodeCont
                         return _nativeTypeMarshaller.GenerateGuaranteedUnmarshalStatements(info, context);
                     }
                     break;
-                case StubCodeContext.Stage.Cleanup:
+                case StubCodeContext.Stage.Cleanup
+                    when !(context.Direction is MarshalDirection.UnmanagedToManaged && (RefKind.Out == info.RefKind || info.ByValueContentsMarshalKind is ByValueContentsMarshalKind.Out)):
+                case StubCodeContext.Stage.CleanupFailure:
                     return _nativeTypeMarshaller.GenerateCleanupStatements(info, context);
+                case StubCodeContext.Stage.AssignOut:
+                    Debug.Assert(MarshallerHelpers.MarshalsOut(info, context));
+                    return _nativeTypeMarshaller.GenerateAssignOutStatements(info, (AssignOutContext)context);
                 default:
                     break;
             }
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/DelegateMarshaller.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/DelegateMarshaller.cs
index 3f8631a3d4ab2a..6696436780422a 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/DelegateMarshaller.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/DelegateMarshaller.cs
@@ -94,6 +94,9 @@ public IEnumerable<StatementSyntax> Generate(TypePositionInfo info, StubCodeCont
                                 ArgumentList(SingletonSeparatedList(Argument(IdentifierName(managedIdentifier))))));
                     }
                     break;
+                case StubCodeContext.Stage.AssignOut:
+                    this.GeneratePointerAssignOut(info, context);
+                    break;
                 default:
                     break;
             }
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 d457e37a7f2b23..129ef98d06847d 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
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System.Collections.Generic;
+using System.Collections.Immutable;
 using System.Linq;
 using Microsoft.CodeAnalysis;
 using Microsoft.CodeAnalysis.CSharp;
@@ -55,6 +56,62 @@ public StatementSyntax GenerateClearManagedValuesDestination(TypePositionInfo in
 
         public abstract StatementSyntax GenerateUnmarshalStatement(TypePositionInfo info, StubCodeContext context);
         public abstract StatementSyntax GenerateElementCleanupStatement(TypePositionInfo info, StubCodeContext context);
+        public abstract TypeSyntax UnmanagedElementType { get; }
+        public StatementSyntax GenerateElementsAssignOutStatement(TypePositionInfo info, AssignOutContext context)
+        {
+            ExpressionSyntax source = IdentifierName(context.GetIdentifiers(info).native);//CollectionSource.GetUnmanagedValuesDestination(info, context.InnerContext);
+            ExpressionSyntax destination;// = CollectionSource.GetUnmanagedValuesDestination(info, context);
+            destination = GetUnmanagedValuesDestinationFromUnmanagedValuesSource(info, context.InnerContext);
+
+            // <native_out>.CopyTo(<UnmanagedValuesDestination>);
+            return ExpressionStatement(
+                InvocationExpression(
+                    MemberAccessExpression(
+                        SyntaxKind.SimpleMemberAccessExpression,
+                        source,
+                        IdentifierName("CopyTo")))
+                .AddArgumentListArguments(
+                    Argument(destination)));
+        }
+
+        /// <summary>
+        /// Returns syntax for an invocation that will create a destination for unmanaged values from the unmanaged values source.
+        /// Necessary to marshal ByValue [Out] in unmanaged to managed stubs.
+        /// <code>MemoryMarshal.CreateSpan(ref Unsafe.AsRef(in __GetUnmanagedValuesSource__.GetPinnableReference(), __numElements__))</code>
+        /// </summary>
+        public InvocationExpressionSyntax GetUnmanagedValuesDestinationFromUnmanagedValuesSource(TypePositionInfo info, StubCodeContext context)
+        {
+            return InvocationExpression(
+                MemberAccessExpression(
+                    SyntaxKind.SimpleMemberAccessExpression,
+                    ParseName(TypeNames.System_Runtime_InteropServices_MemoryMarshal),
+                    IdentifierName("CreateSpan")))
+            .WithArgumentList(
+                ArgumentList(
+                    SeparatedList(
+                        new[]
+                        {
+                            Argument(
+                                InvocationExpression(
+                                    MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
+                                        ParseName(TypeNames.System_Runtime_CompilerServices_Unsafe),
+                                        IdentifierName("AsRef")),
+                                    ArgumentList(SingletonSeparatedList(
+                                        Argument(
+                                            InvocationExpression(
+                                                MemberAccessExpression(
+                                                    SyntaxKind.SimpleMemberAccessExpression,
+                                                    CollectionSource.GetUnmanagedValuesSource(info, context),
+                                                    IdentifierName("GetPinnableReference")),
+                                                    ArgumentList()))
+                                        .WithRefKindKeyword(
+                                            Token(SyntaxKind.InKeyword))))))
+                            .WithRefKindKeyword(
+                                Token(SyntaxKind.RefKeyword)),
+                            Argument(
+                                IdentifierName(MarshallerHelpers.GetNumElementsIdentifier(info, context)))
+                        })));
+        }
     }
 
 #pragma warning disable SA1400 // Access modifier should be declared https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3659
@@ -98,6 +155,8 @@ internal sealed class BlittableElementsMarshalling : ElementsMarshalling
         private readonly TypeSyntax _managedElementType;
         private readonly TypeSyntax _unmanagedElementType;
 
+        public override TypeSyntax UnmanagedElementType => _unmanagedElementType;
+
         public BlittableElementsMarshalling(TypeSyntax managedElementType, TypeSyntax unmanagedElementType, IElementsMarshallingCollectionSource collectionSource)
             : base(collectionSource)
         {
@@ -107,40 +166,49 @@ public BlittableElementsMarshalling(TypeSyntax managedElementType, TypeSyntax un
 
         public override StatementSyntax GenerateUnmanagedToManagedByValueOutMarshalStatement(TypePositionInfo info, StubCodeContext context)
         {
-            // MemoryMarshal.CreateSpan(ref MemoryMarshal.GetReference(<GetUnmanagedValuesSource>), <GetUnmanagedValuesSource>.Length)
-            ExpressionSyntax destination = CastToManagedIfNecessary(
-                InvocationExpression(
-                    MemberAccessExpression(
-                        SyntaxKind.SimpleMemberAccessExpression,
-                        ParseName(TypeNames.System_Runtime_InteropServices_MemoryMarshal),
-                        IdentifierName("CreateSpan")),
-                    ArgumentList(
-                        SeparatedList(new[]
-                        {
-                            Argument(
-                                InvocationExpression(
-                                    MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
-                                        ParseName(TypeNames.System_Runtime_InteropServices_MemoryMarshal),
-                                        IdentifierName("GetReference")),
-                                    ArgumentList(SingletonSeparatedList(
-                                        Argument(CollectionSource.GetUnmanagedValuesSource(info, context))))))
-                                .WithRefKindKeyword(
-                                    Token(SyntaxKind.RefKeyword)),
-                            Argument(
-                                MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
-                                    CollectionSource.GetUnmanagedValuesSource(info, context),
-                                    IdentifierName("Length")))
-                        }))));
-
-            // <GetManagedValuesDestination>.CopyTo(<source>);
-            return ExpressionStatement(
+            ExpressionSyntax destination;
+            List<StatementSyntax> statements = new();
+            var numElementsAssignment = CollectionSource.GetNumElementsAssignmentFromManagedValuesSource(info, context);
+            statements.Add(numElementsAssignment);
+            if (MarshallerHelpers.MarshalsOut(info, context))
+            {
+                // #pragma warning disable CS9081
+                // <native_out> = stackalloc <unmanagedType>[numElementsExpression]
+                // #pragma warning restore CS9081
+                statements.Add(ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
+                    IdentifierName(context.GetIdentifiers(info).native),
+                    StackAllocArrayCreationExpression(
+                        ArrayType(_unmanagedElementType,
+                            SingletonList(ArrayRankSpecifier(SingletonSeparatedList<ExpressionSyntax>(
+                                IdentifierName(MarshallerHelpers.GetNumElementsIdentifier(info, context)))))))))
+                    .WithLeadingTrivia(Trivia(
+                        PragmaWarningDirectiveTrivia(
+                            Token(SyntaxKind.DisableKeyword),
+                            SingletonSeparatedList<ExpressionSyntax>(IdentifierName("CS9081")),
+                            isActive: true)))
+                    .WithTrailingTrivia(Trivia(
+                        PragmaWarningDirectiveTrivia(
+                            Token(SyntaxKind.RestoreKeyword),
+                            SingletonSeparatedList<ExpressionSyntax>(IdentifierName("CS9081")),
+                            isActive: true))));
+                destination = IdentifierName(context.GetIdentifiers(info).native);
+            }
+            else
+            {
+                // MemoryMarshal.CreateSpan(ref MemoryMarshal.GetReference(<GetUnmanagedValuesSource>), <GetUnmanagedValuesSource>.Length)
+                destination = CastToManagedIfNecessary(GetUnmanagedValuesDestinationFromUnmanagedValuesSource(info, context));
+            }
+            statements.Add(ExpressionStatement(
                 InvocationExpression(
                     MemberAccessExpression(
                         SyntaxKind.SimpleMemberAccessExpression,
                         CollectionSource.GetManagedValuesDestination(info, context),
                         IdentifierName("CopyTo")))
                 .AddArgumentListArguments(
-                    Argument(destination)));
+                    Argument(destination))));
+
+            // <GetManagedValuesDestination>.CopyTo(<source>);
+            return Block(statements);
         }
 
         public override StatementSyntax GenerateMarshalStatement(TypePositionInfo info, StubCodeContext context)
@@ -260,6 +328,8 @@ public NonBlittableElementsMarshalling(
             _elementInfo = elementInfo;
         }
 
+        public override TypeSyntax UnmanagedElementType => _unmanagedElementType;
+
         public override StatementSyntax GenerateMarshalStatement(TypePositionInfo info, StubCodeContext context)
         {
             string managedSpanIdentifier = MarshallerHelpers.GetManagedSpanIdentifier(info, context);
@@ -268,6 +338,7 @@ public override StatementSyntax GenerateMarshalStatement(TypePositionInfo info,
             // ReadOnlySpan<T> <managedSpan> = <GetManagedValuesSource>
             // Span<TUnmanagedElement> <nativeSpan> = <GetUnmanagedValuesDestination>
             // <if multidimensional collection> <nativeSpan>.Clear()
+            // <if marshalling to local> <param_native_out> = Unsafe.AsPointer(ref <nativeSpan>.GetPinnableReference())
             // << marshal contents >>
             var statements = new List<StatementSyntax>()
             {
@@ -440,7 +511,7 @@ public override StatementSyntax GenerateElementCleanupStatement(TypePositionInfo
                 indexConstraintName,
                 _elementInfo,
                 _elementMarshaller,
-                StubCodeContext.Stage.Cleanup);
+                context.CurrentStage);
 
             if (contentsCleanupStatements.IsKind(SyntaxKind.EmptyStatement))
             {
@@ -453,6 +524,13 @@ public override StatementSyntax GenerateElementCleanupStatement(TypePositionInfo
                 }
                 return EmptyStatement();
             }
+            ExpressionSyntax spanInit = context.Direction == MarshalDirection.ManagedToUnmanaged
+                                ? CollectionSource.GetUnmanagedValuesDestination(info, context)
+                                : CollectionSource.GetUnmanagedValuesSource(info, context);
+            if (context.CurrentStage is StubCodeContext.Stage.CleanupFailure && info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out))
+            {
+                spanInit = IdentifierName(context.GetIdentifiers(info).native);
+            }
 
             return Block(
                 LocalDeclarationStatement(VariableDeclaration(
@@ -462,10 +540,7 @@ public override StatementSyntax GenerateElementCleanupStatement(TypePositionInfo
                 SingletonSeparatedList(
                     VariableDeclarator(
                         Identifier(nativeSpanIdentifier))
-                    .WithInitializer(EqualsValueClause(
-                            context.Direction == MarshalDirection.ManagedToUnmanaged
-                                ? CollectionSource.GetUnmanagedValuesDestination(info, context)
-                                : CollectionSource.GetUnmanagedValuesSource(info, context)))))),
+                    .WithInitializer(EqualsValueClause(spanInit))))),
                 contentsCleanupStatements);
         }
 
@@ -481,6 +556,51 @@ public override StatementSyntax GenerateUnmanagedToManagedByValueOutMarshalState
 
             var setNumElements = CollectionSource.GetNumElementsAssignmentFromManagedValuesDestination(info, context);
 
+            if (MarshallerHelpers.MarshalsOut(info, context))
+            {
+                // #pragma warning disable CS9081
+                // <native_out> = stackalloc <unmanagedType>[numElementsExpression]
+                // #pragma warning restore CS9081
+                var outInit = ExpressionStatement(AssignmentExpression(
+                    SyntaxKind.SimpleAssignmentExpression,
+                    IdentifierName(context.GetIdentifiers(info).native),
+                    StackAllocArrayCreationExpression(
+                        ArrayType(_unmanagedElementType,
+                            SingletonList(ArrayRankSpecifier(SingletonSeparatedList<ExpressionSyntax>(
+                                IdentifierName(MarshallerHelpers.GetNumElementsIdentifier(info, context)))))))));
+                var nativeSpanDeclaration = LocalDeclarationStatement(VariableDeclaration(
+                    GenericName(
+                        Identifier(TypeNames.System_Span),
+                        TypeArgumentList(
+                            SingletonSeparatedList(_unmanagedElementType))
+                    ),
+                    SingletonSeparatedList(VariableDeclarator(nativeSpanIdentifier)
+                        .WithInitializer(EqualsValueClause(
+                            IdentifierName(context.GetIdentifiers(info).native))))));
+
+                LocalDeclarationStatementSyntax managedSpanDeclaration = LocalDeclarationStatement(VariableDeclaration(
+                    GenericName(
+                        Identifier(TypeNames.System_Span),
+                        TypeArgumentList(SingletonSeparatedList(_elementInfo.ManagedType.Syntax))),
+                    SingletonSeparatedList(
+                        VariableDeclarator(
+                            Identifier(managedSpanIdentifier))
+                        .WithInitializer(EqualsValueClause(
+                        CollectionSource.GetManagedValuesDestination(info, context))))));
+                return Block(
+                    setNumElements,
+                    outInit,
+                    nativeSpanDeclaration,
+                    managedSpanDeclaration,
+                    GenerateContentsMarshallingStatement(
+                        info,
+                        context,
+                        IdentifierName(numElementsIdentifier),
+                        _elementInfo,
+                        new FreeAlwaysOwnedOriginalValueGenerator(_elementMarshaller),
+                        StubCodeContext.Stage.Marshal,
+                        StubCodeContext.Stage.PinnedMarshal));
+            }
             // Span<TUnmanagedElement> <nativeSpan> = MemoryMarshal.CreateSpan(ref Unsafe.AsRef(in <GetUnmanagedValuesSource>.GetPinnableReference(), <numElements>));
             LocalDeclarationStatementSyntax unmanagedValuesSource = LocalDeclarationStatement(VariableDeclaration(
                 GenericName(
@@ -488,37 +608,7 @@ public override StatementSyntax GenerateUnmanagedToManagedByValueOutMarshalState
                     TypeArgumentList(
                         SingletonSeparatedList(_unmanagedElementType))
                 ),
-                SingletonSeparatedList(VariableDeclarator(nativeSpanIdentifier).WithInitializer(EqualsValueClause(
-                    InvocationExpression(
-                        MemberAccessExpression(
-                            SyntaxKind.SimpleMemberAccessExpression,
-                            ParseName(TypeNames.System_Runtime_InteropServices_MemoryMarshal),
-                            IdentifierName("CreateSpan")))
-                    .WithArgumentList(
-                        ArgumentList(
-                            SeparatedList(
-                                new[]
-                                {
-                                    Argument(
-                                        InvocationExpression(
-                                            MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
-                                                ParseName(TypeNames.System_Runtime_CompilerServices_Unsafe),
-                                                IdentifierName("AsRef")),
-                                            ArgumentList(SingletonSeparatedList(
-                                                Argument(
-                                                    InvocationExpression(
-                                                        MemberAccessExpression(
-                                                            SyntaxKind.SimpleMemberAccessExpression,
-                                                            CollectionSource.GetUnmanagedValuesSource(info, context),
-                                                            IdentifierName("GetPinnableReference")),
-                                                            ArgumentList()))
-                                                .WithRefKindKeyword(
-                                                    Token(SyntaxKind.InKeyword))))))
-                                    .WithRefKindKeyword(
-                                        Token(SyntaxKind.RefKeyword)),
-                                    Argument(
-                                        IdentifierName(numElementsIdentifier))
-                                }))))))));
+                SingletonSeparatedList(VariableDeclarator(nativeSpanIdentifier).WithInitializer(EqualsValueClause(GetUnmanagedValuesDestinationFromUnmanagedValuesSource(info, context))))));
 
             // Span<TElement> <managedSpan> = <GetManagedValuesDestination>
             LocalDeclarationStatementSyntax managedValuesDestination = LocalDeclarationStatement(VariableDeclaration(
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ICustomTypeMarshallingStrategy.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ICustomTypeMarshallingStrategy.cs
index f9da5d32b39778..dd210092be180e 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ICustomTypeMarshallingStrategy.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ICustomTypeMarshallingStrategy.cs
@@ -13,6 +13,8 @@ internal interface ICustomTypeMarshallingStrategy
     {
         ManagedTypeInfo AsNativeType(TypePositionInfo info);
 
+        IEnumerable<StatementSyntax> GenerateAssignOutStatements(TypePositionInfo info, AssignOutContext context);
+
         IEnumerable<StatementSyntax> GenerateCleanupStatements(TypePositionInfo info, StubCodeContext context);
 
         IEnumerable<StatementSyntax> GenerateGuaranteedUnmarshalStatements(TypePositionInfo info, StubCodeContext context);
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshalOutContext.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshalOutContext.cs
new file mode 100644
index 00000000000000..ab23ff2d3bd224
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshalOutContext.cs
@@ -0,0 +1,35 @@
+﻿// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+
+namespace Microsoft.Interop
+{
+    /// <summary>
+    /// A <see cref="StubCodeContext"/> that uses the "out" postfixed local variable as the native identifier.
+    /// Meant to be used during the Marshal and PinnedMarshal stages for pairs of (<see cref="TypePositionInfo"/>, <see cref="StubCodeContext"/>) that return true from <see cref="MarshallerHelpers.MarshalsOut(TypePositionInfo, StubCodeContext)"/>
+    /// </summary>
+    internal sealed record MarshalOutContext : StubCodeContext
+    {
+        internal StubCodeContext InnerContext { get; init; }
+
+        internal MarshalOutContext(StubCodeContext inner)
+        {
+            InnerContext = inner;
+            CurrentStage = inner.CurrentStage;
+            Direction = inner.Direction;
+            ParentContext = inner.ParentContext;
+        }
+
+        public override (TargetFramework framework, Version version) GetTargetFramework() => InnerContext.GetTargetFramework();
+
+        public override bool SingleFrameSpansNativeContext => InnerContext.SingleFrameSpansNativeContext;
+
+        public override bool AdditionalTemporaryStateLivesAcrossStages => InnerContext.AdditionalTemporaryStateLivesAcrossStages;
+
+        public override (string managed, string native) GetIdentifiers(TypePositionInfo info)
+            => (InnerContext.GetIdentifiers(info).managed, InnerContext.GetAdditionalIdentifier(info, "out"));
+
+        public override string GetAdditionalIdentifier(TypePositionInfo info, string name) => InnerContext.GetAdditionalIdentifier(info, name);
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs
index 86275796f208ee..0eab01d092f26a 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs
@@ -3,6 +3,7 @@
 
 using System;
 using System.Collections.Generic;
+using System.Collections.Immutable;
 using Microsoft.CodeAnalysis;
 using Microsoft.CodeAnalysis.CSharp;
 using Microsoft.CodeAnalysis.CSharp.Syntax;
@@ -394,5 +395,49 @@ public static MarshalDirection GetMarshalDirection(TypePositionInfo info, StubCo
             }
             throw new UnreachableException("An element is either a return value or passed by value or by ref.");
         }
+
+        /// <summary>
+        /// Returns whether the parameter must be marshalled back to a native callee.
+        /// In COM, this means the parameter should be marshalled to a local variable in the Marshal and PinnedMarshal stages
+        /// and copied to the parameter value in the AssignOut stage.
+        /// </summary>
+        public static bool MarshalsOut(TypePositionInfo info, StubCodeContext context)
+            => context.Direction is MarshalDirection.UnmanagedToManaged // UnmanagedToManaged is the only direction with a native callee
+                && context.AdditionalTemporaryStateLivesAcrossStages // if AdditionTempStateLivesAcrossStages is false, it is an element of an array
+                && ((info.IsByRef && info.RefKind is RefKind.Out or RefKind.Ref) // out and ref need to be marshalled back to the callee
+                    || info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out) // [Out] needs it's contents marshalled back to native
+                    || (info.IsManagedReturnPosition && !info.IsNativeReturnPosition)); // Managed returns on non-PreserveSig methods are 'out'
+
+        /// <summary>
+        /// Generates the following statements
+        /// <code>_ = <paramref name="identifier"/>;</code>
+        /// </summary>
+        public static StatementSyntax CreateDiscardStatement(string identifier)
+            => ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName("_"), IdentifierName(identifier)));
+
+        /// <summary>
+        /// Generates the statement
+        /// <code>*<paramref name="pointerIdentifier"/> = <paramref name="valueIdentifier"/>;</code>
+        /// </summary>
+        public static ExpressionStatementSyntax GenerateAssignmentToPointerValue(string pointerIdentifier, string valueIdentifier)
+        {
+            return ExpressionStatement(
+                AssignmentExpression(
+                    SyntaxKind.SimpleAssignmentExpression,
+                    PrefixUnaryExpression(SyntaxKind.PointerIndirectionExpression, IdentifierName(pointerIdentifier)),
+                    IdentifierName(valueIdentifier)));
+        }
+
+        /// <summary>
+        /// Returns the default AssignOut statement for pointer parameters.
+        /// Throws if <see cref="MarshalsOut(TypePositionInfo, StubCodeContext)"/> is false.
+        /// <inheritdoc cref="GenerateAssignmentToPointerValue(string, string)"/>
+        /// </summary>
+        public static ImmutableArray<ExpressionStatementSyntax> GenerateDefaultAssignOutStatement(TypePositionInfo info, AssignOutContext context)
+        {
+            if (!MarshalsOut(info, context))
+                throw new ArgumentException("Cannot make an AssignOut statement for a parameter that is not marshalled out");
+            return ImmutableArray.Create(GenerateAssignmentToPointerValue(context.ParameterIdentifier, context.GetIdentifiers(info).native));
+        }
     }
 }
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorExtensions.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorExtensions.cs
index 2c11351959b038..a673d14e73f4cd 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorExtensions.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorExtensions.cs
@@ -155,7 +155,7 @@ private static bool TryRehydrateMarshalAsAttribute(TypePositionInfo info, out At
                     CustomTypeMarshallerData defaultMarshallerData = collectionMarshalling.Marshallers.GetModeOrDefault(MarshalMode.Default);
                     if ((defaultMarshallerData.MarshallerType.FullTypeName.StartsWith($"{TypeNames.System_Runtime_InteropServices_ArrayMarshaller}<")
                         || defaultMarshallerData.MarshallerType.FullTypeName.StartsWith($"{TypeNames.System_Runtime_InteropServices_PointerArrayMarshaller}<"))
-                        && defaultMarshallerData.CollectionElementMarshallingInfo is NoMarshallingInfo or MarshalAsInfo {  UnmanagedType: not UnmanagedType.CustomMarshaler })
+                        && defaultMarshallerData.CollectionElementMarshallingInfo is NoMarshallingInfo or MarshalAsInfo { UnmanagedType: not UnmanagedType.CustomMarshaler })
                     {
                         countInfo = collectionMarshalling.ElementCountInfo;
                         elementMarshallingInfo = defaultMarshallerData.CollectionElementMarshallingInfo;
@@ -256,10 +256,24 @@ public static ArgumentSyntax AsManagedArgument(this IMarshallingGenerator genera
             return Argument(IdentifierName(managedIdentifier));
         }
 
-        public static ExpressionSyntax GenerateNativeByRefInitialization(this IMarshallingGenerator generator, TypePositionInfo info, StubCodeContext context)
+        /// <summary>
+        /// Generates <code>*__p_native_param</code>
+        /// </summary>
+        public static ExpressionSyntax GenerateParameterValueDereference(this IMarshallingGenerator generator, TypePositionInfo info, StubCodeContext context)
+        {
+            string paramIdentifier = generator.AsParameter(info, context).Identifier.Text;
+            return PrefixUnaryExpression(SyntaxKind.PointerIndirectionExpression, IdentifierName(paramIdentifier));
+        }
+
+        /// <summary>
+        /// If the parameter should marshal to a local and assign out, generates a statement to copy the pointed to value to the parameter.
+        /// Throws if the arguments are not meant to be marshalled out to a native caller.
+        /// </summary>
+        public static ExpressionStatementSyntax GeneratePointerAssignOut(this IMarshallingGenerator generator, TypePositionInfo info, StubCodeContext context)
         {
-            string paramIdentifier = context.GetAdditionalIdentifier(info, ParameterIdentifierSuffix);
-            return RefExpression(PrefixUnaryExpression(SyntaxKind.PointerIndirectionExpression, IdentifierName(paramIdentifier)));
+            if (!MarshallerHelpers.MarshalsOut(info, context))
+                throw new ArgumentException("");
+            return MarshallerHelpers.GenerateAssignmentToPointerValue(generator.AsParameter(info, context).Identifier.ToString(), context.GetIdentifiers(info).native);
         }
     }
 }
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs
index 03a906f8881597..c1227216c59f33 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System.Collections.Generic;
+using System.Diagnostics;
 using Microsoft.CodeAnalysis;
 using Microsoft.CodeAnalysis.CSharp;
 using Microsoft.CodeAnalysis.CSharp.Syntax;
@@ -190,6 +191,12 @@ public static string GetMarshallerIdentifier(TypePositionInfo info, StubCodeCont
         {
             return context.GetAdditionalIdentifier(info, MarshallerIdentifier);
         }
+
+        public IEnumerable<StatementSyntax> GenerateAssignOutStatements(TypePositionInfo info, AssignOutContext context)
+        {
+            Debug.Assert(MarshallerHelpers.MarshalsOut(info, context));
+            return MarshallerHelpers.GenerateDefaultAssignOutStatement(info, context);
+        }
     }
 
     /// <summary>
@@ -284,6 +291,8 @@ public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context)
 
         public IEnumerable<StatementSyntax> GenerateGuaranteedUnmarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateGuaranteedUnmarshalStatements(info, context);
         public IEnumerable<StatementSyntax> GenerateNotifyForSuccessfulInvokeStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateNotifyForSuccessfulInvokeStatements(info, context);
+        public IEnumerable<StatementSyntax> GenerateAssignOutStatements(TypePositionInfo info, AssignOutContext context)
+            => _innerMarshaller.GenerateAssignOutStatements(info, context);
     }
 
     internal sealed class StatefulLinearCollectionSource : IElementsMarshallingCollectionSource
@@ -355,12 +364,14 @@ internal sealed class StatefulLinearCollectionMarshalling : ICustomTypeMarshalli
         private readonly ExpressionSyntax _numElementsExpression;
         private readonly ElementsMarshalling _elementsMarshalling;
         private readonly bool _cleanupElements;
+        private readonly TypeSyntax _unmanagedCollectionType;
 
         public StatefulLinearCollectionMarshalling(
             ICustomTypeMarshallingStrategy innerMarshaller,
             MarshallerShape shape,
             ExpressionSyntax numElementsExpression,
             ElementsMarshalling elementsMarshalling,
+            TypeSyntax unmanagedCollectionType,
             bool cleanupElements)
         {
             _innerMarshaller = innerMarshaller;
@@ -368,12 +379,13 @@ public StatefulLinearCollectionMarshalling(
             _numElementsExpression = numElementsExpression;
             _elementsMarshalling = elementsMarshalling;
             _cleanupElements = cleanupElements;
+            _unmanagedCollectionType = unmanagedCollectionType;
         }
 
         public ManagedTypeInfo AsNativeType(TypePositionInfo info) => _innerMarshaller.AsNativeType(info);
         public IEnumerable<StatementSyntax> GenerateCleanupStatements(TypePositionInfo info, StubCodeContext context)
         {
-            if (!_cleanupElements)
+            if (!(_cleanupElements || MarshallerHelpers.MarshalsOut(info, context)))
             {
                 yield break;
             }
@@ -444,6 +456,16 @@ public IEnumerable<StatementSyntax> GenerateSetupStatements(TypePositionInfo inf
                 {
                     InstanceIdentifier = numElementsIdentifier
                 }, context);
+
+            if (MarshallerHelpers.MarshalsOut(info, context)
+                && info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out))
+            {
+                yield return MarshallerHelpers.Declare(
+                    ScopedType(GenericName(
+                        Identifier(TypeNames.System_Span),
+                        TypeArgumentList(SingletonSeparatedList(_elementsMarshalling.UnmanagedElementType)))),
+                    context.GetAdditionalIdentifier(info, "out"), true);
+            }
         }
 
         public IEnumerable<StatementSyntax> GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context)
@@ -488,6 +510,19 @@ public IEnumerable<StatementSyntax> GenerateUnmarshalStatements(TypePositionInfo
         public IEnumerable<StatementSyntax> GenerateUnmarshalCaptureStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateUnmarshalCaptureStatements(info, context);
 
         public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => true;
+        public IEnumerable<StatementSyntax> GenerateAssignOutStatements(TypePositionInfo info, AssignOutContext context)
+        {
+            Debug.Assert(MarshallerHelpers.MarshalsOut(info, context));
+            if (info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out))
+            {
+                yield return _elementsMarshalling.GenerateElementsAssignOutStatement(info, context);
+            }
+            else
+            {
+                foreach (var s in _innerMarshaller.GenerateAssignOutStatements(info, context))
+                    yield return s;
+            }
+        }
     }
 
     /// <summary>
@@ -534,5 +569,6 @@ public IEnumerable<StatementSyntax> GenerateCleanupStatements(TypePositionInfo i
         public IEnumerable<StatementSyntax> GenerateUnmarshalCaptureStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateUnmarshalCaptureStatements(info, context);
 
         public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.UsesNativeIdentifier(info, context);
+        public IEnumerable<StatementSyntax> GenerateAssignOutStatements(TypePositionInfo info, AssignOutContext context) => _innerMarshaller.GenerateAssignOutStatements(info, context);
     }
 }
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatelessMarshallingStrategy.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatelessMarshallingStrategy.cs
index 24cfcca03df60b..aa97d7193731cb 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatelessMarshallingStrategy.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatelessMarshallingStrategy.cs
@@ -3,6 +3,7 @@
 
 using System;
 using System.Collections.Generic;
+using System.Diagnostics;
 using Microsoft.CodeAnalysis;
 using Microsoft.CodeAnalysis.CSharp;
 using Microsoft.CodeAnalysis.CSharp.Syntax;
@@ -138,6 +139,12 @@ public IEnumerable<StatementSyntax> GenerateNotifyForSuccessfulInvokeStatements(
         {
             return Array.Empty<StatementSyntax>();
         }
+
+        public IEnumerable<StatementSyntax> GenerateAssignOutStatements(TypePositionInfo info, AssignOutContext context)
+        {
+            Debug.Assert(MarshallerHelpers.MarshalsOut(info, context));
+            return MarshallerHelpers.GenerateDefaultAssignOutStatement(info, context);
+        }
     }
 
     /// <summary>
@@ -251,6 +258,7 @@ IEnumerable<StatementSyntax> GenerateCallerAllocatedBufferMarshalStatements()
         public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.UsesNativeIdentifier(info, context);
 
         public IEnumerable<StatementSyntax> GenerateNotifyForSuccessfulInvokeStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateNotifyForSuccessfulInvokeStatements(info, context);
+        public IEnumerable<StatementSyntax> GenerateAssignOutStatements(TypePositionInfo info, AssignOutContext context) => _innerMarshaller.GenerateAssignOutStatements(info, context);
     }
 
     internal sealed class StatelessFreeMarshalling : ICustomTypeMarshallingStrategy
@@ -265,6 +273,7 @@ public StatelessFreeMarshalling(ICustomTypeMarshallingStrategy innerMarshaller,
         }
 
         public ManagedTypeInfo AsNativeType(TypePositionInfo info) => _innerMarshaller.AsNativeType(info);
+        public IEnumerable<StatementSyntax> GenerateAssignOutStatements(TypePositionInfo info, AssignOutContext context) => _innerMarshaller.GenerateAssignOutStatements(info, context);
 
         public IEnumerable<StatementSyntax> GenerateCleanupStatements(TypePositionInfo info, StubCodeContext context)
         {
@@ -316,6 +325,12 @@ public ManagedTypeInfo AsNativeType(TypePositionInfo info)
             return _unmanagedType;
         }
 
+        public IEnumerable<StatementSyntax> GenerateAssignOutStatements(TypePositionInfo info, AssignOutContext context)
+        {
+            Debug.Assert(MarshallerHelpers.MarshalsOut(info, context));
+            return MarshallerHelpers.GenerateDefaultAssignOutStatement(info, context);
+        }
+
         public IEnumerable<StatementSyntax> GenerateCleanupStatements(TypePositionInfo info, StubCodeContext context)
         {
             if (MarshallerHelpers.GetMarshalDirection(info, context) == MarshalDirection.ManagedToUnmanaged)
@@ -553,10 +568,23 @@ public StatelessLinearCollectionMarshalling(
         }
 
         public ManagedTypeInfo AsNativeType(TypePositionInfo info) => _unmanagedType;
+        public IEnumerable<StatementSyntax> GenerateAssignOutStatements(TypePositionInfo info, AssignOutContext context)
+        {
+            Debug.Assert(MarshallerHelpers.MarshalsOut(info, context));
+            if (info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out))
+            {
+                yield return _elementsMarshalling.GenerateElementsAssignOutStatement(info, context);
+            }
+            else
+            {
+                foreach (var s in _spaceMarshallingStrategy.GenerateAssignOutStatements(info, context))
+                    yield return s;
+            }
+        }
 
         public IEnumerable<StatementSyntax> GenerateCleanupStatements(TypePositionInfo info, StubCodeContext context)
         {
-            if (!_cleanupElementsAndSpace)
+            if (!(_cleanupElementsAndSpace || MarshallerHelpers.MarshalsOut(info, context)))
             {
                 yield break;
             }
@@ -577,9 +605,12 @@ public IEnumerable<StatementSyntax> GenerateCleanupStatements(TypePositionInfo i
                 yield return elementCleanup;
             }
 
-            foreach (var statement in _spaceMarshallingStrategy.GenerateCleanupStatements(info, context))
+            if (!_cleanupElementsAndSpace)
             {
-                yield return statement;
+                foreach (var statement in _spaceMarshallingStrategy.GenerateCleanupStatements(info, context))
+                {
+                    yield return statement;
+                }
             }
         }
 
@@ -627,6 +658,15 @@ public IEnumerable<StatementSyntax> GenerateSetupStatements(TypePositionInfo inf
             {
                 yield return elementsSetup;
             }
+            if (MarshallerHelpers.MarshalsOut(info, context)
+                && info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out))
+            {
+                yield return MarshallerHelpers.Declare(
+                    ScopedType(GenericName(
+                        Identifier(TypeNames.System_Span),
+                        TypeArgumentList(SingletonSeparatedList(_elementsMarshalling.UnmanagedElementType)))),
+                    context.GetAdditionalIdentifier(info, "out"), true);
+            }
         }
 
         public IEnumerable<StatementSyntax> GenerateUnmarshalCaptureStatements(TypePositionInfo info, StubCodeContext context) => Array.Empty<StatementSyntax>();
@@ -646,6 +686,10 @@ public IEnumerable<StatementSyntax> GenerateUnmarshalStatements(TypePositionInfo
                 // If the parameter is marshalled by-value [Out], then we don't marshal the contents of the collection.
                 // We do clear the span, so that if the invoke target doesn't fill it, we aren't left with undefined content.
                 yield return _elementsMarshalling.GenerateClearManagedValuesDestination(info, context);
+                foreach (var statement in _spaceMarshallingStrategy.GenerateUnmarshalStatements(info, context))
+                {
+                    yield return statement;
+                }
                 yield break;
             }
 
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..44d6dfe5b820bc 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
@@ -3,120 +3,11 @@
 
 using System;
 using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
 using Microsoft.CodeAnalysis.CSharp.Syntax;
 using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
 
 namespace Microsoft.Interop
 {
-    /// <summary>
-    /// Marshalling strategy that introduces a variable to hold the initial value of the provided <see cref="TypePositionInfo"/> and a variable to track if the original value has been replaced.
-    /// </summary>
-    /// <seealso cref="CleanupOwnedOriginalValueMarshalling" />
-    internal sealed class UnmanagedToManagedOwnershipTrackingStrategy : ICustomTypeMarshallingStrategy
-    {
-        private readonly ICustomTypeMarshallingStrategy _innerMarshaller;
-
-        public UnmanagedToManagedOwnershipTrackingStrategy(ICustomTypeMarshallingStrategy innerMarshaller)
-        {
-            _innerMarshaller = innerMarshaller;
-        }
-
-        public ManagedTypeInfo AsNativeType(TypePositionInfo info) => _innerMarshaller.AsNativeType(info);
-
-        public IEnumerable<StatementSyntax> GenerateCleanupStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateCleanupStatements(info, context);
-
-        public IEnumerable<StatementSyntax> GenerateGuaranteedUnmarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateGuaranteedUnmarshalStatements(info, context);
-        public IEnumerable<StatementSyntax> GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context)
-        {
-            foreach (StatementSyntax statement in _innerMarshaller.GenerateMarshalStatements(info, context))
-            {
-                yield return statement;
-            }
-
-            // Now that we've set the new value to pass to the caller on the <native> identifier, we need to make sure that we free the old one.
-            // The caller will not see the old one any more, so it won't be able to free it.
-
-            // <ownOriginalValue> = true;
-            yield return ExpressionStatement(
-                AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
-                    IdentifierName(context.GetAdditionalIdentifier(info, OwnershipTrackingHelpers.OwnOriginalValueIdentifier)),
-                    LiteralExpression(SyntaxKind.TrueLiteralExpression)));
-        }
-
-        public IEnumerable<StatementSyntax> GenerateNotifyForSuccessfulInvokeStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateNotifyForSuccessfulInvokeStatements(info, context);
-        public IEnumerable<StatementSyntax> GeneratePinnedMarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GeneratePinnedMarshalStatements(info, context);
-
-        public IEnumerable<StatementSyntax> GeneratePinStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GeneratePinStatements(info, context);
-        public IEnumerable<StatementSyntax> GenerateSetupStatements(TypePositionInfo info, StubCodeContext context)
-        {
-            foreach (StatementSyntax statement in _innerMarshaller.GenerateSetupStatements(info, context))
-            {
-                yield return statement;
-            }
-
-            // bool <ownOriginalValue> = false;
-            yield return LocalDeclarationStatement(
-                VariableDeclaration(
-                    PredefinedType(Token(SyntaxKind.BoolKeyword)),
-                    SingletonSeparatedList(
-                        VariableDeclarator(
-                            Identifier(context.GetAdditionalIdentifier(info, OwnershipTrackingHelpers.OwnOriginalValueIdentifier)),
-                            null,
-                            EqualsValueClause(
-                                LiteralExpression(SyntaxKind.FalseLiteralExpression))))));
-
-            yield return OwnershipTrackingHelpers.DeclareOriginalValueIdentifier(info, context, AsNativeType(info));
-        }
-
-        public IEnumerable<StatementSyntax> GenerateUnmarshalCaptureStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateUnmarshalCaptureStatements(info, context);
-
-        public IEnumerable<StatementSyntax> GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateUnmarshalStatements(info, context);
-        public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.UsesNativeIdentifier(info, context);
-    }
-
-    /// <summary>
-    /// Marshalling strategy that uses the tracking variables introduced by <see cref="UnmanagedToManagedOwnershipTrackingStrategy"/> to cleanup the original value if the original value is owned
-    /// in the <see cref="StubCodeContext.Stage.Cleanup"/> stage.
-    /// </summary>
-    internal sealed class CleanupOwnedOriginalValueMarshalling : ICustomTypeMarshallingStrategy
-    {
-        private readonly ICustomTypeMarshallingStrategy _innerMarshaller;
-
-        public CleanupOwnedOriginalValueMarshalling(ICustomTypeMarshallingStrategy innerMarshaller)
-        {
-            _innerMarshaller = innerMarshaller;
-        }
-
-        public ManagedTypeInfo AsNativeType(TypePositionInfo info) => _innerMarshaller.AsNativeType(info);
-
-        public IEnumerable<StatementSyntax> GenerateCleanupStatements(TypePositionInfo info, StubCodeContext context)
-        {
-            // if (<ownOriginalValue>)
-            // {
-            //     <cleanup>
-            // }
-            yield return IfStatement(
-                IdentifierName(context.GetAdditionalIdentifier(info, OwnershipTrackingHelpers.OwnOriginalValueIdentifier)),
-                Block(_innerMarshaller.GenerateCleanupStatements(info, new OwnedValueCodeContext(context))));
-        }
-
-        public IEnumerable<StatementSyntax> GenerateGuaranteedUnmarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateGuaranteedUnmarshalStatements(info, context);
-        public IEnumerable<StatementSyntax> GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateMarshalStatements(info, context);
-
-        public IEnumerable<StatementSyntax> GenerateNotifyForSuccessfulInvokeStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateNotifyForSuccessfulInvokeStatements(info, context);
-        public IEnumerable<StatementSyntax> GeneratePinnedMarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GeneratePinnedMarshalStatements(info, context);
-
-        public IEnumerable<StatementSyntax> GeneratePinStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GeneratePinStatements(info, context);
-        public IEnumerable<StatementSyntax> GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateSetupStatements(info, context);
-
-        public IEnumerable<StatementSyntax> GenerateUnmarshalCaptureStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateUnmarshalCaptureStatements(info, context);
-
-        public IEnumerable<StatementSyntax> GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateUnmarshalStatements(info, context);
-        public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.UsesNativeIdentifier(info, context);
-    }
-
     /// <summary>
     /// Marshalling strategy to cache the initial value of a given <see cref="TypePositionInfo"/> 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 <see cref="StubCodeContext.Stage.Cleanup"/> stage, so additional ownership tracking is extraneous.
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..f3315f8ced94e7 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
@@ -2,7 +2,6 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System;
-using System.Collections.Generic;
 
 namespace Microsoft.Interop
 {
@@ -72,7 +71,18 @@ public enum Stage
             /// Convert native data to managed data even in the case of an exception during
             /// the non-cleanup phases.
             /// </summary>
-            GuaranteedUnmarshal
+            GuaranteedUnmarshal,
+
+            /// <summary>
+            /// In scenarios where necessary (unmanaged to managed stubs), assign marshalled values out to the parameters.
+            /// Separating this from <see cref="Marshal"/> ensures parameters remain unmodified when the method returns a failing return value.
+            /// </summary>
+            AssignOut,
+
+            /// <summary>
+            /// In scenarios where the managed callee throws before returning, this stage cleans up any resources that the method allocated but cannot transfer to the caller.
+            /// </summary>
+            CleanupFailure
         }
 
         /// <summary>
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/VariableDeclarations.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/VariableDeclarations.cs
index c791ec1f268a0a..0a90a3144e9435 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/VariableDeclarations.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/VariableDeclarations.cs
@@ -4,7 +4,6 @@
 using System.Collections.Immutable;
 using Microsoft.CodeAnalysis;
 using Microsoft.CodeAnalysis.CSharp.Syntax;
-using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
 
 namespace Microsoft.Interop
 {
@@ -53,22 +52,23 @@ public static VariableDeclarations GenerateDeclarationsForManagedToUnmanaged(Bou
 
             static void AppendVariableDeclarations(ImmutableArray<LocalDeclarationStatementSyntax>.Builder statementsToUpdate, BoundGenerator marshaller, StubCodeContext context, bool initializeToDefault)
             {
-                (string managed, string native) = context.GetIdentifiers(marshaller.TypeInfo);
+                TypePositionInfo info = marshaller.TypeInfo;
+                (string managed, string native) = context.GetIdentifiers(info);
 
                 // Declare variable for return value
-                if (marshaller.TypeInfo.IsManagedReturnPosition || marshaller.TypeInfo.IsNativeReturnPosition)
+                if (info.IsManagedReturnPosition || info.IsNativeReturnPosition)
                 {
                     statementsToUpdate.Add(MarshallerHelpers.Declare(
-                        marshaller.TypeInfo.ManagedType.Syntax,
+                        info.ManagedType.Syntax,
                         managed,
                         initializeToDefault));
                 }
 
                 // Declare variable with native type for parameter or return value
-                if (marshaller.Generator.UsesNativeIdentifier(marshaller.TypeInfo, context))
+                if (marshaller.Generator.UsesNativeIdentifier(info, context))
                 {
                     statementsToUpdate.Add(MarshallerHelpers.Declare(
-                        marshaller.Generator.AsNativeType(marshaller.TypeInfo).Syntax,
+                        marshaller.Generator.AsNativeType(info).Syntax,
                         native,
                         initializeToDefault));
                 }
@@ -83,7 +83,10 @@ public static VariableDeclarations GenerateDeclarationsForUnmanagedToManaged(Bou
             foreach (BoundGenerator marshaller in marshallers.NativeParameterMarshallers)
             {
                 TypePositionInfo info = marshaller.TypeInfo;
-                if (info.IsNativeReturnPosition || info.IsManagedReturnPosition)
+                if (info.IsNativeReturnPosition)
+                    continue;
+
+                if (info.IsManagedReturnPosition)
                     continue;
 
                 // Declare variables for parameters
@@ -110,63 +113,66 @@ public static VariableDeclarations GenerateDeclarationsForUnmanagedToManaged(Bou
 
             static void AppendVariableDeclarations(ImmutableArray<LocalDeclarationStatementSyntax>.Builder statementsToUpdate, BoundGenerator marshaller, StubCodeContext context, bool initializeToDefault)
             {
-                (string managed, string native) = context.GetIdentifiers(marshaller.TypeInfo);
+                var info = marshaller.TypeInfo;
+                (string managed, string native) = context.GetIdentifiers(info);
 
                 // Declare variable for return value
-                if (marshaller.TypeInfo.IsNativeReturnPosition)
+                if (info.IsNativeReturnPosition)
                 {
-                    bool nativeReturnUsesNativeIdentifier = marshaller.Generator.UsesNativeIdentifier(marshaller.TypeInfo, context);
+                    bool nativeReturnUsesNativeIdentifier = marshaller.Generator.UsesNativeIdentifier(info, context);
 
                     // Always initialize the return value.
                     statementsToUpdate.Add(MarshallerHelpers.Declare(
-                        marshaller.TypeInfo.ManagedType.Syntax,
+                        info.ManagedType.Syntax,
                         managed,
                         initializeToDefault || !nativeReturnUsesNativeIdentifier));
 
                     if (nativeReturnUsesNativeIdentifier)
                     {
                         statementsToUpdate.Add(MarshallerHelpers.Declare(
-                            marshaller.Generator.AsNativeType(marshaller.TypeInfo).Syntax,
+                            marshaller.Generator.AsNativeType(info).Syntax,
                             native,
                             initializeToDefault: true));
                     }
                 }
                 else
                 {
-                    ValueBoundaryBehavior boundaryBehavior = marshaller.Generator.GetValueBoundaryBehavior(marshaller.TypeInfo, context);
+                    ValueBoundaryBehavior boundaryBehavior = marshaller.Generator.GetValueBoundaryBehavior(info, context);
 
                     // Declare variable with native type for parameter
                     // if the marshaller uses the native identifier and the signature uses a different identifier
                     // than the native identifier.
-                    if (marshaller.Generator.UsesNativeIdentifier(marshaller.TypeInfo, context)
+                    if (marshaller.Generator.UsesNativeIdentifier(info, context)
                         && boundaryBehavior is not
                             (ValueBoundaryBehavior.NativeIdentifier or ValueBoundaryBehavior.CastNativeIdentifier))
                     {
-                        TypeSyntax localType = marshaller.Generator.AsNativeType(marshaller.TypeInfo).Syntax;
-                        if (boundaryBehavior != ValueBoundaryBehavior.AddressOfNativeIdentifier)
+                        TypeSyntax localType = marshaller.Generator.AsNativeType(info).Syntax;
+                        if (MarshallerHelpers.MarshalsOut(info, context)
+                            && !info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out))
                         {
+                            string outlocal = context.GetAdditionalIdentifier(info, "out");
+                            // <nativeType> __param_native_out;
                             statementsToUpdate.Add(MarshallerHelpers.Declare(
                                 localType,
-                                native,
-                                false));
+                                outlocal,
+                                true));
                         }
-                        else
+
+                        if (boundaryBehavior is ValueBoundaryBehavior.AddressOfNativeIdentifier
+                            && MarshallerHelpers.GetMarshalDirection(info, context) is MarshalDirection.UnmanagedToManaged or MarshalDirection.Bidirectional)
                         {
-                            // To simplify propogating back the value to the "byref" parameter,
-                            // we'll just declare the native identifier as a ref to its type.
-                            // The rest of the code we generate will work as expected, and we don't need
-                            // to manually propogate back the updated values after the call.
+                            // If we need to unmarshal, initialize the native in value
                             statementsToUpdate.Add(MarshallerHelpers.Declare(
-                                RefType(localType),
+                                localType,
                                 native,
-                                marshaller.Generator.GenerateNativeByRefInitialization(marshaller.TypeInfo, context)));
+                                marshaller.Generator.GenerateParameterValueDereference(info, context)));
                         }
                     }
 
                     if (boundaryBehavior != ValueBoundaryBehavior.ManagedIdentifier)
                     {
                         statementsToUpdate.Add(MarshallerHelpers.Declare(
-                            marshaller.TypeInfo.ManagedType.Syntax,
+                            info.ManagedType.Syntax,
                             managed,
                             initializeToDefault));
                     }
diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/ComInterfaceGenerator.Tests.csproj b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/ComInterfaceGenerator.Tests.csproj
index b0262f1f0ca548..4f37f6ff80b02d 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/ComInterfaceGenerator.Tests.csproj
+++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/ComInterfaceGenerator.Tests.csproj
@@ -7,6 +7,7 @@
     <IncludeRemoteExecutor>true</IncludeRemoteExecutor>
     <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
     <!-- Declare InteropCompilerGeneratedFilesOutputPath to put generated files in a single repo to easily view diffs -->
+    <InteropCompilerGeneratedFilesOutputPath>\src\GeneratedCode\</InteropCompilerGeneratedFilesOutputPath>
     <CompilerGeneratedFilesOutputPath Condition="'$(InteropCompilerGeneratedFilesOutputPath)' == ''">$(OutputPath)\Generated</CompilerGeneratedFilesOutputPath>
     <CompilerGeneratedFilesOutputPath Condition="'$(InteropCompilerGeneratedFilesOutputPath)' != ''">$(InteropCompilerGeneratedFilesOutputPath)\ComInterfaceGenerator.Tests</CompilerGeneratedFilesOutputPath>
     <EnableDefaultItems>true</EnableDefaultItems>
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 cca4aa23ea2a9e..76d8004c789cd4 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/RcwAroundCcwTests.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/RcwAroundCcwTests.cs
@@ -2,12 +2,12 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System;
+using System.Linq;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices.Marshalling;
 using SharedTypes.ComInterfaces;
 using SharedTypes.ComInterfaces.MarshallingFails;
 using Xunit;
-using static ComInterfaceGenerator.Tests.ComInterfaces;
 
 namespace ComInterfaceGenerator.Tests
 {
@@ -23,17 +23,26 @@ public partial class RcwAroundCcwTests
         }
 
         [Fact]
-        public void IGetAndSetInt()
-        {
-            var obj = CreateWrapper<GetAndSetInt, IGetAndSetInt>();
-            obj.SetInt(1);
-            Assert.Equal(1, obj.GetInt());
+        public void IInt()
+        {
+            var obj = CreateWrapper<IIntImpl, IInt>();
+            obj.Set(1);
+            Assert.Equal(1, obj.Get());
+            var local = 4;
+            obj.SwapRef(ref local);
+            Assert.Equal(1, local);
+            Assert.Equal(4, obj.Get());
+            local = 2;
+            obj.SetIn(in local);
+            local = 0;
+            obj.GetOut(out local);
+            Assert.Equal(2, local);
         }
 
         [Fact]
         public void IDerived()
         {
-            var obj = CreateWrapper<Derived, IDerived>();
+            IDerived obj = CreateWrapper<Derived, IDerived>();
             obj.SetInt(1);
             Assert.Equal(1, obj.GetInt());
             obj.SetName("A");
@@ -63,10 +72,13 @@ public void IIntArray()
             var obj = CreateWrapper<IIntArrayImpl, IIntArray>();
             int[] data = new int[] { 1, 2, 3 };
             int length = data.Length;
-            obj.Set(data, length);
-            Assert.Equal(data, obj.Get(out int _));
-            obj.Get2(out var value);
+            obj.SetContents(data, length);
+            Assert.Equal(data, obj.GetReturn(out int _));
+            obj.GetOut(out var value);
             Assert.Equal(data, value);
+            obj.SwapArray(ref data, data.Length);
+            obj.PassIn(in data, data.Length);
+            obj.Double(data, data.Length);
         }
 
         [Fact]
@@ -89,8 +101,11 @@ public void IInterface()
         {
             var iint = CreateWrapper<IIntImpl, IInt>();
             var obj = CreateWrapper<IInterfaceImpl, IInterface>();
-            obj.Set(iint);
+            obj.SetInt(iint);
             _ = obj.Get();
+            obj.SwapRef(ref iint);
+            obj.InInt(in iint);
+            obj.GetOut(out var _);
         }
 
         [Fact]
@@ -99,14 +114,13 @@ public void ICollectionMarshallingFails()
             var obj = CreateWrapper<ICollectionMarshallingFailsImpl, ICollectionMarshallingFails>();
 
             Assert.Throws<ArgumentException>(() =>
-                _ = obj.Get()
+                _ = obj.Get(out _)
             );
             Assert.Throws<ArgumentException>(() =>
-                obj.Set(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 })
+                obj.Set(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }, 10)
             );
         }
 
-        [ActiveIssue("https://github.com/dotnet/runtime/issues/88111")]
         [Fact]
         public void IJaggedArrayMarshallingFails()
         {
@@ -116,8 +130,8 @@ public void IJaggedArrayMarshallingFails()
                 _ = obj.Get(out _, out _)
             );
             var array = new int[][] { new int[] { 1, 2, 3 }, new int[] { 4, 5, }, new int[] { 6, 7, 8, 9 } };
-            var length = 3;
             var widths = new int[] { 3, 2, 4 };
+            var length = 3;
             Assert.Throws<ArgumentException>(() =>
                 obj.Set(array, widths, length)
             );
@@ -147,11 +161,10 @@ public void IStringArrayMarshallingFails()
             {
                 obj.OutParam(out strings);
             });
-            // https://github.com/dotnet/runtime/issues/87845
-            //Assert.Throws<ArgumentException>(() =>
-            //{
-            //    obj.ByValueOutParam(strings);
-            //});
+            Assert.Throws<ArgumentException>(() =>
+            {
+                obj.ByValueOutParam(strings);
+            });
             Assert.Throws<ArgumentException>(() =>
             {
                 obj.ByValueInOutParam(strings);
@@ -161,260 +174,60 @@ public void IStringArrayMarshallingFails()
                 _ = obj.ReturnValue();
             });
         }
-    }
-
-    public static partial class ComInterfaces
-    {
-        [GeneratedComInterface]
-        [Guid("EE6D1F2A-3418-4317-A87C-35488F6546AB")]
-        internal partial interface IInt
-        {
-            public int Get();
-            public void Set(int value);
-        }
-
-        [GeneratedComClass]
-        internal partial class IIntImpl : IInt
-        {
-            int _data;
-            public int Get() => _data;
-            public void Set(int value) => _data = value;
-        }
-
-        [GeneratedComInterface]
-        [Guid("5A9D3ED6-CC17-4FB9-8F82-0070489B7213")]
-        internal partial interface IBool
-        {
-            [return: MarshalAs(UnmanagedType.I1)]
-            bool Get();
-            void Set([MarshalAs(UnmanagedType.I1)] bool value);
-        }
 
-        [GeneratedComClass]
-        internal partial class IBoolImpl : IBool
+        [Fact]
+        public void IArrayOfStatelessElements()
         {
-            bool _data;
-            public bool Get() => _data;
-            public void Set(bool value) => _data = value;
-        }
+            var obj = CreateWrapper<ArrayOfStatelessElements, IArrayOfStatelessElements>();
+            var originalData = GetStartingValue();
+            var data = GetStartingValue();
+            var refData = GetStartingValue().Select(a => new StatelessType() { I = a.I * 2 }).ToArray();
+            var outData = GetStartingValue().Reverse().ToArray();
 
-        [GeneratedComInterface]
-        [Guid("9FA4A8A9-2D8F-48A8-B6FB-B44B5F1B9FB6")]
-        internal partial interface IFloat
-        {
-            float Get();
-            void Set(float value);
-        }
+            obj.Method(data, data.Length);
+            AssertEqual(originalData, data);
 
-        [GeneratedComClass]
-        internal partial class IFloatImpl : IFloat
-        {
-            float _data;
-            public float Get() => _data;
-            public void Set(float value) => _data = value;
-        }
+            obj.MethodIn(in data, data.Length);
+            AssertEqual(originalData, data);
 
-        [GeneratedComInterface]
-        [Guid("9FA4A8A9-3D8F-48A8-B6FB-B45B5F1B9FB6")]
-        internal partial interface IIntArray
-        {
-            [return: MarshalUsing(CountElementName = nameof(size))]
-            int[] Get(out int size);
-            int Get2([MarshalUsing(CountElementName = MarshalUsingAttribute.ReturnsCountValue)] out int[] array);
-            void Set([MarshalUsing(CountElementName = nameof(size))] int[] array, int size);
-        }
+            obj.MethodContentsIn(data, data.Length);
+            AssertEqual(originalData, data);
 
-        [GeneratedComClass]
-        internal partial class IIntArrayImpl : IIntArray
-        {
-            int[] _data;
-            public int[] Get(out int size)
-            {
-                size = _data.Length;
-                return _data;
-            }
-            public int Get2(out int[] array)
-            {
-                array = _data;
-                return array.Length;
-            }
-            public void Set(int[] array, int size)
-            {
-                _data = array;
-            }
-        }
-
-        [GeneratedComInterface]
-        [Guid("9FA4A8A9-3D8F-48A8-B6FB-B45B5F1B9FB6")]
-        internal partial interface IJaggedIntArray
-        {
-            [return: MarshalUsing(CountElementName = nameof(length)),
-                MarshalUsing(ElementIndirectionDepth = 1, CountElementName = nameof(widths))]
-            int[][] Get(
-                [MarshalUsing(CountElementName = nameof(length))]
-                out int[] widths,
-                out int length);
+            obj.MethodOut(out data, data.Length);
+            AssertEqual(outData, data);
 
-            int Get2(
-                [MarshalUsing(CountElementName = MarshalUsingAttribute.ReturnsCountValue),
-                MarshalUsing(ElementIndirectionDepth = 1, CountElementName = nameof(widths))]
-                out int[][] array,
-                [MarshalUsing(CountElementName = MarshalUsingAttribute.ReturnsCountValue)]
-                out int[] widths);
+            data = GetStartingValue();
+            obj.MethodContentsOut(data, data.Length);
+            AssertEqual(outData, data);
 
-            void Set(
-                [MarshalUsing(CountElementName = nameof(length)),
-                MarshalUsing(ElementIndirectionDepth = 1, CountElementName = nameof(widths))]
-                int[][] array,
-                [MarshalUsing(CountElementName = nameof(length))]
-                int[] widths,
-                int length);
-        }
+            data = GetStartingValue();
+            obj.MethodRef(ref data, data.Length);
+            AssertEqual(refData, data);
 
-        [GeneratedComClass]
-        internal partial class IJaggedIntArrayImpl : IJaggedIntArray
-        {
-            int[][] _data = new int[][] { new int[] { 1, 2, 3 }, new int[] { 4, 5 }, new int[] { 6, 7, 8, 9 } };
-            int[] _widths = new int[] { 3, 2, 4 };
-            public int[][] Get(out int[] widths, out int length)
-            {
-                widths = _widths;
-                length = _data.Length;
-                return _data;
-            }
-            public int Get2(out int[][] array, out int[] widths)
-            {
-                array = _data;
-                widths = _widths;
-                return array.Length;
-            }
-            public void Set(int[][] array, int[] widths, int length)
-            {
-                _data = array;
-                _widths = widths;
-            }
-        }
+            data = GetStartingValue();
+            obj.MethodContentsInOut(data, data.Length);
+            AssertEqual(refData, data);
 
-        [CustomMarshaller(typeof(int), MarshalMode.ElementIn, typeof(ThrowOn4thElementMarshalled))]
-        [CustomMarshaller(typeof(int), MarshalMode.ElementOut, typeof(ThrowOn4thElementMarshalled))]
-        internal static class ThrowOn4thElementMarshalled
-        {
-            static int _marshalledCount = 0;
-            static int _unmarshalledCount = 0;
-            public static nint ConvertToUnmanaged(int managed)
+            static void AssertEqual(StatelessType[] param1, StatelessType[] param2)
             {
-                if (_marshalledCount++ == 3)
+                Assert.Equal(param1.Length, param2.Length);
+                for (int i = 0; i < param1.Length; i++)
                 {
-                    _marshalledCount = 0;
-                    throw new ArgumentException("The element was the 4th element (with 0-based index 3)");
+                    Assert.Equal(param1[i].I, param2[i].I);
                 }
-                return managed;
             }
 
-            public static int ConvertToManaged(nint unmanaged)
+            static StatelessType[] GetStartingValue()
             {
-                if (_unmarshalledCount++ == 3)
+                return new StatelessType[]
                 {
-                    _unmarshalledCount = 0;
-                    throw new ArgumentException("The element was the 4th element (with 0-based index 3)");
-                }
-                return (int)unmanaged;
-            }
-        }
-
-        [GeneratedComInterface]
-        [Guid("A4857395-06FB-4A6E-81DB-35461BE999C5")]
-        internal partial interface ICollectionMarshallingFails
-        {
-            [return: MarshalUsing(ConstantElementCount = 10)]
-            [return: MarshalUsing(typeof(ThrowOn4thElementMarshalled), ElementIndirectionDepth = 1)]
-            public int[] Get();
-            public void Set(
-                [MarshalUsing(ConstantElementCount = 10)]
-                [MarshalUsing(typeof(ThrowOn4thElementMarshalled), ElementIndirectionDepth = 1)]
-                int[] value);
-        }
-
-        [GeneratedComClass]
-        public partial class ICollectionMarshallingFailsImpl : ICollectionMarshallingFails
-        {
-            int[] _data = new[] { 1, 2, 3 };
-            public int[] Get() => _data;
-            public void Set(int[] value) => _data = value;
-        }
-
-        [GeneratedComInterface]
-        [Guid("9FA4A8A9-3D8F-48A8-B6FB-B45B5F1B9FB6")]
-        internal partial interface IJaggedIntArrayMarshallingFails
-        {
-            [return: MarshalUsing(CountElementName = nameof(length)),
-                MarshalUsing(ElementIndirectionDepth = 1, CountElementName = nameof(widths)),
-                MarshalUsing(typeof(ThrowOn4thElementMarshalled), ElementIndirectionDepth = 2)]
-            int[][] Get(
-                [MarshalUsing(CountElementName = nameof(length))]
-                out int[] widths,
-                out int length);
-
-            int Get2(
-                [MarshalUsing(CountElementName = MarshalUsingAttribute.ReturnsCountValue),
-                MarshalUsing(ElementIndirectionDepth = 1, CountElementName = nameof(widths)),
-                MarshalUsing(typeof(ThrowOn4thElementMarshalled), ElementIndirectionDepth = 2)]
-                out int[][] array,
-                [MarshalUsing(CountElementName = MarshalUsingAttribute.ReturnsCountValue)]
-                out int[] widths);
-
-            void Set(
-                [MarshalUsing(CountElementName = nameof(length)),
-                MarshalUsing(ElementIndirectionDepth = 1, CountElementName = nameof(widths)),
-                MarshalUsing(typeof(ThrowOn4thElementMarshalled), ElementIndirectionDepth = 2)]
-                int[][] array,
-                [MarshalUsing(CountElementName = nameof(length))]
-                int[] widths,
-                int length);
-        }
-
-        [GeneratedComClass]
-        internal partial class IJaggedIntArrayMarshallingFailsImpl : IJaggedIntArrayMarshallingFails
-        {
-            int[][] _data = new int[][] { new int[] { 1, 2, 3 }, new int[] { 4, 5 }, new int[] { 6, 7, 8, 9 } };
-            int[] _widths = new int[] { 3, 2, 4 };
-            public int[][] Get(out int[] widths, out int length)
-            {
-                widths = _widths;
-                length = _data.Length;
-                return _data;
-            }
-            public int Get2(out int[][] array, out int[] widths)
-            {
-                array = _data;
-                widths = _widths;
-                return array.Length;
-            }
-            public void Set(int[][] array, int[] widths, int length)
-            {
-                _data = array;
-                _widths = widths;
-            }
-        }
-
-        [GeneratedComInterface]
-        [Guid("A4857398-06FB-4A6E-81DB-35461BE999C5")]
-        internal partial interface IInterface
-        {
-            public IInt Get();
-            public void Set(IInt value);
-        }
-
-        [GeneratedComClass]
-        public partial class IInterfaceImpl : IInterface
-        {
-            IInt _data = new IIntImpl();
-            IInt IInterface.Get() => _data;
-            void IInterface.Set(IInt value)
-            {
-                int x = value.Get();
-                value.Set(x);
-                _data = value;
+                    new StatelessType() {I = 5},
+                    new StatelessType() {I = 4},
+                    new StatelessType() {I = 3},
+                    new StatelessType() {I = 2},
+                    new StatelessType() {I = 1},
+                    new StatelessType() {I = 0}
+                };
             }
         }
     }
diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/UnmanagedToManagedCustomMarshallingTests.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/UnmanagedToManagedCustomMarshallingTests.cs
index 54e96f3b268f8f..33943867854284 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/UnmanagedToManagedCustomMarshallingTests.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/UnmanagedToManagedCustomMarshallingTests.cs
@@ -2,14 +2,11 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System;
-using System.Collections.Generic;
 using System.Linq;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices.Marshalling;
-using System.Text;
 using System.Threading;
-using System.Threading.Tasks;
 using SharedTypes;
 using Xunit;
 using static ComInterfaceGenerator.Tests.UnmanagedToManagedCustomMarshallingTests;
@@ -416,6 +413,8 @@ public struct Ref
 
                 private TUnmanaged* _originalUnmanaged;
                 private TUnmanaged* _unmanaged;
+                private TUnmanaged* Unmanaged => _unmanaged == null ? _unmanaged = (TUnmanaged*)Marshal.AllocCoTaskMem(sizeof(TUnmanaged) * _managed.Length) : _unmanaged;
+
                 private TManaged[] _managed;
 
                 public void FromUnmanaged(TUnmanaged* unmanaged)
@@ -451,7 +450,7 @@ public void FromManaged(TManaged[] managed)
 
                 public TUnmanaged* ToUnmanaged()
                 {
-                    return _unmanaged = (TUnmanaged*)Marshal.AllocCoTaskMem(sizeof(TUnmanaged) * _managed.Length); 
+                    return Unmanaged;
                 }
 
                 public ReadOnlySpan<TManaged> GetManagedValuesSource()
@@ -461,7 +460,7 @@ public ReadOnlySpan<TManaged> GetManagedValuesSource()
 
                 public Span<TUnmanaged> GetUnmanagedValuesDestination()
                 {
-                    return new(_unmanaged, _managed.Length);
+                    return new(Unmanaged, _managed.Length);
                 }
             }
         }
diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CompileFails.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CompileFails.cs
index 4fbe5cabbcd803..ea91fa0b7454ec 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CompileFails.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CompileFails.cs
@@ -6,7 +6,6 @@
 using System.Diagnostics;
 using System.Linq;
 using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
 using System.Runtime.InteropServices.Marshalling;
 using System.Threading.Tasks;
 using Microsoft.CodeAnalysis;
@@ -780,11 +779,12 @@ public static IEnumerable<object[]> ByValueMarshalAttributeOnPinnedMarshalledTyp
                     .WithLocation(1)
                     .WithLocation(2)
                     .WithArguments(SR.InOutAttributes, paramName, SR.PinnedMarshallingIsInOutByDefault);
-            yield return new object[] {
-                ID(),
-                codeSnippets.ByValueMarshallingOfType(inAttribute + outAttribute + constElementCount, "int[]", paramNameWithLocation),
-                new DiagnosticResult[] { inOutAttributeIsDefaultDiagnostic }
-            };
+            // https://github.com/dotnet/runtime/issues/89265
+            //yield return new object[] {
+            //    ID(),
+            //    codeSnippets.ByValueMarshallingOfType(inAttribute + outAttribute + constElementCount, "int[]", paramNameWithLocation),
+            //    new DiagnosticResult[] { inOutAttributeIsDefaultDiagnostic }
+            //};
             yield return new object[] {
                 ID(),
                 codeSnippets.ByValueMarshallingOfType(inAttribute + outAttribute + constElementCount, "char[]", paramNameWithLocation, (StringMarshalling.Utf16, null)),
diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/CollectionMarshallingFails.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/CollectionMarshallingFails.cs
index 3e51f406db3da6..ec5ac6f6518595 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/CollectionMarshallingFails.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/CollectionMarshallingFails.cs
@@ -208,16 +208,6 @@ public void MultiDimensionalOutArray_EnsureAllCleaned()
         {
             var arr = GetMultiDimensionalArray<BoolStruct>(10, 10);
             var widths = new int[10] { 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 };
-            //foreach (var throwOn in new int[] { 0, 1, 45, 99 })
-            //{
-            //    EnforceAllElementsCleanedUpBoolStruct.ThrowOnNthUnmarshalledElement(throwOn);
-            //    EnforceAllElementsCleanedUpBoolStruct.ExpectedCleanupNumber = 100;
-            //    Assert.Throws<ArgumentException>(() =>
-            //    {
-            //        NativeExportsNE.MarshallingFails.NegateBoolsOut2D(arr, arr.Length, widths, out BoolStruct[][] boolsOut);
-            //    });
-            //    EnforceAllElementsCleanedUpBoolStruct.AssertAllHaveBeenCleaned();
-            //}
             // Run without throwing - this is okay only because the native code doesn't actually use the array, it creates a whole new one
             EnforceAllElementsCleanedUpBoolStruct.ThrowOnNthUnmarshalledElement(-1);
             EnforceAllElementsCleanedUpBoolStruct.ExpectedCleanupNumber = 100;
diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/LibraryImportGenerator.Tests.csproj b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/LibraryImportGenerator.Tests.csproj
index 9b91d1800dc395..38b9bda2a469b8 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/LibraryImportGenerator.Tests.csproj
+++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/LibraryImportGenerator.Tests.csproj
@@ -7,13 +7,13 @@
     <ReferencesNativeExports>true</ReferencesNativeExports>
     <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
     <!-- Declare InteropCompilerGeneratedFilesOutputPath to put generated files in a single repo to easily view diffs -->
+    <InteropCompilerGeneratedFilesOutputPath>\src\GeneratedCode\</InteropCompilerGeneratedFilesOutputPath>
     <CompilerGeneratedFilesOutputPath Condition="'$(InteropCompilerGeneratedFilesOutputPath)' == ''">$(OutputPath)\Generated</CompilerGeneratedFilesOutputPath>
     <CompilerGeneratedFilesOutputPath Condition="'$(InteropCompilerGeneratedFilesOutputPath)' != ''">$(InteropCompilerGeneratedFilesOutputPath)\LibraryImportGenerator.Tests</CompilerGeneratedFilesOutputPath>
   </PropertyGroup>
 
   <ItemGroup>
-    <Compile Include="$(CommonPath)DisableRuntimeMarshalling.cs"
-             Link="Common\DisableRuntimeMarshalling.cs" />
+    <Compile Include="$(CommonPath)DisableRuntimeMarshalling.cs" Link="Common\DisableRuntimeMarshalling.cs" />
   </ItemGroup>
 
   <ItemGroup>
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/ComInterfaceGenerator/ArrayMarshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/ComInterfaceGenerator/ArrayMarshalling.cs
index c8f2292a6985c1..67b227c51b943f 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/ComInterfaceGenerator/ArrayMarshalling.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/ComInterfaceGenerator/ArrayMarshalling.cs
@@ -53,7 +53,7 @@ static void* GetIntArrayVTable
                 if (obj is ImplementingObject)
                 {
                     ComInterfaceEntry* comInterfaceEntry = (ComInterfaceEntry*)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(ImplementingObject), sizeof(ComInterfaceEntry));
-                    comInterfaceEntry->IID = new Guid(IGetIntArray._guid);
+                    comInterfaceEntry->IID = new Guid(IGetIntArray.IID);
                     comInterfaceEntry->Vtable = (nint)GetIntArrayVTable;
                     count = 1;
                     return comInterfaceEntry;
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/ComInterfaceGenerator/GetAndSetInt.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/ComInterfaceGenerator/GetAndSetInt.cs
index 66faa8c577e7c2..c9a149e12798c7 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/ComInterfaceGenerator/GetAndSetInt.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/ComInterfaceGenerator/GetAndSetInt.cs
@@ -3,15 +3,8 @@
 
 using System;
 using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
-using System.Runtime.InteropServices.Marshalling;
-using System.Runtime.InteropServices.ObjectiveC;
-using System.Text;
-using System.Threading.Tasks;
 using SharedTypes.ComInterfaces;
 using static System.Runtime.InteropServices.ComWrappers;
 
@@ -55,7 +48,7 @@ static void* s_comInterface1VTable
                 if (obj is ImplementingObject)
                 {
                     ComInterfaceEntry* comInterfaceEntry = (ComInterfaceEntry*)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(ImplementingObject), sizeof(ComInterfaceEntry));
-                    comInterfaceEntry->IID = new Guid(IGetAndSetInt._guid);
+                    comInterfaceEntry->IID = new Guid(IGetAndSetInt.IID);
                     comInterfaceEntry->Vtable = (nint)s_comInterface1VTable;
                     count = 1;
                     return comInterfaceEntry;
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/ComInterfaceGenerator/StringMarshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/ComInterfaceGenerator/StringMarshalling.cs
index 9059f53c4cc8ae..06c52cfa5000ab 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/ComInterfaceGenerator/StringMarshalling.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/ComInterfaceGenerator/StringMarshalling.cs
@@ -81,7 +81,7 @@ static void* S_Utf16VTable
 				if (obj is IUTF8Marshalling)
 				{
 					ComInterfaceEntry* comInterfaceEntry = (ComInterfaceEntry*)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(Utf8Implementation), sizeof(ComInterfaceEntry));
-					comInterfaceEntry->IID = new Guid(IUTF8Marshalling._guid);
+					comInterfaceEntry->IID = new Guid(IUTF8Marshalling.IID);
 					comInterfaceEntry->Vtable = (nint)S_Utf8VTable;
 					count = 1;
 					return comInterfaceEntry;
@@ -89,7 +89,7 @@ static void* S_Utf16VTable
 				else if (obj is IUTF16Marshalling)
 				{
 					ComInterfaceEntry* comInterfaceEntry = (ComInterfaceEntry*)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(Utf16Implementation), sizeof(ComInterfaceEntry));
-					comInterfaceEntry->IID = new Guid(IUTF16Marshalling._guid);
+					comInterfaceEntry->IID = new Guid(IUTF16Marshalling.IID);
 					comInterfaceEntry->Vtable = (nint)S_Utf16VTable;
 					count = 1;
 					return comInterfaceEntry;
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/ComInterfaceGenerator/StringMarshallingOverride.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/ComInterfaceGenerator/StringMarshallingOverride.cs
index df01a1045700be..8d5c14fa96c2c2 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/ComInterfaceGenerator/StringMarshallingOverride.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/ComInterfaceGenerator/StringMarshallingOverride.cs
@@ -76,9 +76,9 @@ static void* S_DerivedVTable
                 if (obj is IStringMarshallingOverrideDerived)
                 {
                     ComInterfaceEntry* comInterfaceEntry = (ComInterfaceEntry*)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(Implementation), sizeof(ComInterfaceEntry) * 2);
-                    comInterfaceEntry[0].IID = new Guid(IStringMarshallingOverrideDerived._guid);
+                    comInterfaceEntry[0].IID = new Guid(IStringMarshallingOverrideDerived.IID);
                     comInterfaceEntry[0].Vtable = (nint)S_DerivedVTable;
-                    comInterfaceEntry[1].IID = new Guid(IStringMarshallingOverride._guid);
+                    comInterfaceEntry[1].IID = new Guid(IStringMarshallingOverride.IID);
                     comInterfaceEntry[1].Vtable = (nint)S_VTable;
                     count = 2;
                     return comInterfaceEntry;
@@ -86,7 +86,7 @@ static void* S_DerivedVTable
                 if (obj is IStringMarshallingOverride)
                 {
                     ComInterfaceEntry* comInterfaceEntry = (ComInterfaceEntry*)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(Implementation), sizeof(ComInterfaceEntry));
-                    comInterfaceEntry->IID = new Guid(IStringMarshallingOverride._guid);
+                    comInterfaceEntry->IID = new Guid(IStringMarshallingOverride.IID);
                     comInterfaceEntry->Vtable = (nint)S_VTable;
                     count = 1;
                     return comInterfaceEntry;
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj
index 7c5b7e09bf1006..2a7d9b149f94ab 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj
@@ -18,6 +18,13 @@
       '$(TargetOS)' == 'tvossimulator'">true</_TargetsAppleOS>
   </PropertyGroup>
 
+<Target Name="DisableComInterfaceGenerator"
+        BeforeTargets="CoreCompile">
+  <ItemGroup>
+  <Analyzer Remove="@(Analyzer)" Condition="'%(FileName)' == 'Microsoft.Interop.ComInterfaceGenerator'" />
+  </ItemGroup>
+</Target>
+
   <ItemGroup>
     <Compile Include="..\..\TestAssets\SharedTypes\ComInterfaces\**\*.cs" Link="ComInterfaceGenerator\ComInterfaces\%(RecursiveDir)\%(FileName).cs" />
     <Compile Include="$(CommonPath)DisableRuntimeMarshalling.cs" Link="Common\DisableRuntimeMarshalling.cs" />
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IArrayOfStatelessElements.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IArrayOfStatelessElements.cs
new file mode 100644
index 00000000000000..abb8842f1e0a2f
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IArrayOfStatelessElements.cs
@@ -0,0 +1,75 @@
+﻿// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Marshalling;
+
+namespace SharedTypes.ComInterfaces
+{
+    [GeneratedComInterface]
+    [Guid("F4963CBF-10AF-460B-8495-107782187705")]
+    internal partial interface IArrayOfStatelessElements
+    {
+        void Method([MarshalUsing(CountElementName = nameof(size))] StatelessType[] param, int size);
+        void MethodIn([MarshalUsing(CountElementName = nameof(size))] in StatelessType[] param, int size);
+        void MethodOut([MarshalUsing(CountElementName = nameof(size))] out StatelessType[] param, int size);
+        void MethodRef([MarshalUsing(CountElementName = nameof(size))] ref StatelessType[] param, int size);
+        void MethodContentsIn([MarshalUsing(CountElementName = nameof(size))][In] StatelessType[] param, int size);
+        void MethodContentsOut([MarshalUsing(CountElementName = nameof(size))][Out] StatelessType[] param, int size);
+        void MethodContentsInOut([MarshalUsing(CountElementName = nameof(size))][In, Out] StatelessType[] param, int size);
+    }
+
+    [GeneratedComClass]
+    internal partial class ArrayOfStatelessElements : IArrayOfStatelessElements
+    {
+        public void Method(StatelessType[] param, int size)
+        {
+        }
+        public void MethodContentsIn(StatelessType[] param, int size)
+        {
+            // We should be able to modify the contents and the caller shouldn't see it
+            for (int i = 0; i < size; i++)
+            {
+                param[i] = new StatelessType() { I = param[i].I * 2 };
+            }
+        }
+        public void MethodContentsInOut(StatelessType[] param, int size)
+        {
+            for (int i = 0; i < size; i++)
+            {
+                param[i] = new StatelessType() { I = param[i].I * 2 };
+            }
+        }
+        public void MethodContentsOut(StatelessType[] param, int size)
+        {
+            for (int i = 0; i < size; i++)
+            {
+                param[i] = new StatelessType() { I = i };
+            }
+        }
+        public void MethodIn(in StatelessType[] param, int size)
+        {
+            // We should be able to modify the contents and the caller shouldn't see it
+            for (int i = 0; i < size; i++)
+            {
+                param[i] = new StatelessType() { I = param[i].I * 2 };
+            }
+        }
+        public void MethodOut(out StatelessType[] param, int size)
+        {
+            param = new StatelessType[size];
+            for (int i = 0; i < size; i++)
+            {
+                param[i] = new StatelessType() { I = i };
+            }
+        }
+        public void MethodRef(ref StatelessType[] param, int size)
+        {
+            for (int i = 0; i < size; i++)
+            {
+                param[i] = new StatelessType() { I = param[i].I * 2 };
+            }
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IBool.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IBool.cs
new file mode 100644
index 00000000000000..4e71832850fefc
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IBool.cs
@@ -0,0 +1,26 @@
+﻿// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Marshalling;
+
+namespace SharedTypes.ComInterfaces
+{
+    [GeneratedComInterface]
+    [Guid("5A9D3ED6-CC17-4FB9-8F82-0070489B7213")]
+    internal partial interface IBool
+    {
+        [return: MarshalAs(UnmanagedType.I1)]
+        bool Get();
+        void Set([MarshalAs(UnmanagedType.I1)] bool value);
+    }
+
+    [GeneratedComClass]
+    internal partial class IBoolImpl : IBool
+    {
+        bool _data;
+        public bool Get() => _data;
+        public void Set(bool value) => _data = value;
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/ICustomStringMarshallingUtf16.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/ICustomStringMarshallingUtf16.cs
index d792b62d6d5a97..7a1c97a7b37302 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/ICustomStringMarshallingUtf16.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/ICustomStringMarshallingUtf16.cs
@@ -7,7 +7,7 @@
 
 namespace SharedTypes.ComInterfaces
 {
-    [Guid(_guid)]
+    [Guid(IID)]
     [GeneratedComInterface(StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(Utf16StringMarshaller))]
     internal partial interface ICustomStringMarshallingUtf16
     {
@@ -15,6 +15,6 @@ internal partial interface ICustomStringMarshallingUtf16
 
         public void SetString(string value);
 
-        public const string _guid = "E11D5F3E-DD57-41A6-A59E-7D110551A760";
+        public const string IID = "E11D5F3E-DD57-41A6-A59E-7D110551A760";
     }
 }
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IDerived.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IDerived.cs
index 54669fa6c380ec..f6cd4ff8afc55b 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IDerived.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IDerived.cs
@@ -2,22 +2,21 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System;
-using System.Collections.Generic;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices.Marshalling;
 
 namespace SharedTypes.ComInterfaces
 {
     [GeneratedComInterface]
-    [Guid(_guid)]
+    [Guid(IID)]
     internal partial interface IDerived : IGetAndSetInt
     {
         void SetName([MarshalUsing(typeof(Utf16StringMarshaller))] string name);
 
-        [return:MarshalUsing(typeof(Utf16StringMarshaller))]
+        [return: MarshalUsing(typeof(Utf16StringMarshaller))]
         string GetName();
 
-        internal new const string _guid = "7F0DB364-3C04-4487-9193-4BB05DC7B654";
+        internal new const string IID = "7F0DB364-3C04-4487-9193-4BB05DC7B654";
     }
 
     [GeneratedComClass]
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IEmpty.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IEmpty.cs
index e586a04573c9f1..86af99aa4ff726 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IEmpty.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IEmpty.cs
@@ -8,9 +8,9 @@
 namespace SharedTypes.ComInterfaces
 {
     [GeneratedComInterface]
-    [Guid(_guid)]
+    [Guid(IID)]
     internal partial interface IEmpty
     {
-        public const string _guid = "95D19F50-F2D8-4E61-884B-0A9162EA4646";
+        public const string IID = "95D19F50-F2D8-4E61-884B-0A9162EA4646";
     }
 }
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IFloat.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IFloat.cs
new file mode 100644
index 00000000000000..f63cbbb91ab1de
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IFloat.cs
@@ -0,0 +1,25 @@
+﻿// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Marshalling;
+
+namespace SharedTypes.ComInterfaces
+{
+    [GeneratedComInterface]
+    [Guid("9FA4A8A9-2D8F-48A8-B6FB-B44B5F1B9FB6")]
+    internal partial interface IFloat
+    {
+        float Get();
+        void Set(float value);
+    }
+
+    [GeneratedComClass]
+    internal partial class IFloatImpl : IFloat
+    {
+        float _data;
+        public float Get() => _data;
+        public void Set(float value) => _data = value;
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IGetAndSetInt.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IGetAndSetInt.cs
index 54e7fb896bf94f..3f1b18f34e9beb 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IGetAndSetInt.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IGetAndSetInt.cs
@@ -8,14 +8,14 @@
 namespace SharedTypes.ComInterfaces
 {
     [GeneratedComInterface]
-    [Guid(_guid)]
+    [Guid(IID)]
     internal partial interface IGetAndSetInt
     {
         int GetInt();
 
         public void SetInt(int x);
 
-        public const string _guid = "2c3f9903-b586-46b1-881b-adfce9af47b1";
+        public const string IID = "2c3f9903-b586-46b1-881b-adfce9af47b1";
     }
     [GeneratedComClass]
     internal partial class GetAndSetInt : IGetAndSetInt
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IGetIntArray.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IGetIntArray.cs
index b70de07d1596b5..f2283708678df1 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IGetIntArray.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IGetIntArray.cs
@@ -8,12 +8,12 @@
 namespace SharedTypes.ComInterfaces
 {
     [GeneratedComInterface]
-    [Guid(_guid)]
+    [Guid(IID)]
     internal partial interface IGetIntArray
     {
         [return: MarshalUsing(ConstantElementCount = 10)]
         int[] GetInts();
 
-        public const string _guid = "7D802A0A-630A-4C8E-A21F-771CC9031FB9";
+        public const string IID = "7D802A0A-630A-4C8E-A21F-771CC9031FB9";
     }
 }
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IInt.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IInt.cs
new file mode 100644
index 00000000000000..e50344f3a268fd
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IInt.cs
@@ -0,0 +1,47 @@
+﻿// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Marshalling;
+
+namespace SharedTypes.ComInterfaces
+{
+    [GeneratedComInterface]
+    [Guid("EE6D1F2A-3418-4317-A87C-35488F6546AB")]
+    internal partial interface IInt
+    {
+        public int Get();
+        public void Set(int value);
+        public void SwapRef(ref int value);
+        public void GetOut(out int value);
+        public void SetIn(in int value);
+    }
+
+    [GeneratedComClass]
+    internal partial class IIntImpl : IInt
+    {
+        int _data;
+
+        public int Get() => _data;
+
+        public void Set(int value) => _data = value;
+
+        public void SetIn(in int value)
+        {
+            _data = value;
+        }
+
+        public void GetOut(out int value)
+        {
+            value = _data;
+        }
+
+        public void SwapRef(ref int value)
+        {
+            var tmp = _data;
+            _data = value;
+            value = tmp;
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IIntArray.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IIntArray.cs
new file mode 100644
index 00000000000000..fbc68dcf4dbca0
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IIntArray.cs
@@ -0,0 +1,72 @@
+﻿// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Marshalling;
+
+namespace SharedTypes.ComInterfaces
+{
+    [GeneratedComInterface]
+    [Guid("9FA4A8A9-3D8F-48A8-B6FB-B45B5F1B9FB6")]
+    internal partial interface IIntArray
+    {
+        [return: MarshalUsing(CountElementName = nameof(size))]
+        int[] GetReturn(out int size);
+        int GetOut([MarshalUsing(CountElementName = MarshalUsingAttribute.ReturnsCountValue)] out int[] array);
+        void SetContents([MarshalUsing(CountElementName = nameof(size))] int[] array, int size);
+        void FillAscending([Out][MarshalUsing(CountElementName = nameof(size))] int[] array, int size);
+        void Double([In, Out][MarshalUsing(CountElementName = nameof(size))] int[] array, int size);
+        void PassIn([MarshalUsing(CountElementName = nameof(size))] in int[] array, int size);
+        void SwapArray([MarshalUsing(CountElementName = nameof(size))] ref int[] array, int size);
+    }
+
+    [GeneratedComClass]
+    internal partial class IIntArrayImpl : IIntArray
+    {
+        int[] _data;
+        public int[] GetReturn(out int size)
+        {
+            size = _data.Length;
+            return _data;
+        }
+        public int GetOut(out int[] array)
+        {
+            array = _data;
+            return array.Length;
+        }
+        public void SetContents(int[] array, int size)
+        {
+            _data = new int[size];
+            array.CopyTo(_data, 0);
+        }
+
+        public void FillAscending(int[] array, int size)
+        {
+            for (int i = 0; i < size; i++)
+            {
+                array[i] = i;
+            }
+        }
+        public void Double(int[] array, int size)
+        {
+            for (int i = 0; i < size; i++)
+            {
+                array[i] = array[i] * 2;
+            }
+
+        }
+
+        public void PassIn([MarshalUsing(CountElementName = "size")] in int[] array, int size)
+        {
+            _data = new int[size];
+            array.CopyTo(_data, 0);
+        }
+        public void SwapArray([MarshalUsing(CountElementName = "size")] ref int[] array, int size)
+        {
+            var temp = _data;
+            _data = array;
+            array = temp;
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IInterface.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IInterface.cs
new file mode 100644
index 00000000000000..95c6a13335b44d
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IInterface.cs
@@ -0,0 +1,51 @@
+﻿// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Marshalling;
+
+namespace SharedTypes.ComInterfaces
+{
+    [GeneratedComInterface]
+    [Guid("A4857398-06FB-4A6E-81DB-35461BE999C5")]
+    internal partial interface IInterface
+    {
+        public IInt Get();
+        public void SetInt(IInt value);
+        public void SwapRef(ref IInt value);
+        public void GetOut(out IInt value);
+        public void InInt(in IInt value);
+    }
+
+    [GeneratedComClass]
+    internal partial class IInterfaceImpl : IInterface
+    {
+        IInt _data = new IIntImpl();
+
+        IInt IInterface.Get() => _data;
+
+        void IInterface.InInt(in IInt value)
+        {
+            var i = value.Get();
+        }
+
+        void IInterface.GetOut(out IInt value)
+        {
+            value = _data;
+        }
+
+        void IInterface.SwapRef(ref IInt value)
+        {
+            var tmp = _data;
+            _data = value;
+            value = tmp;
+        }
+
+        void IInterface.SetInt(IInt value)
+        {
+            int x = value.Get();
+            value.Set(x);
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IJaggedIntArray.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IJaggedIntArray.cs
new file mode 100644
index 00000000000000..c1153e377fc656
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IJaggedIntArray.cs
@@ -0,0 +1,60 @@
+﻿// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Marshalling;
+
+namespace SharedTypes.ComInterfaces
+{
+    [GeneratedComInterface]
+    [Guid("9FA4A8A9-3D8F-48A8-B6FB-B45B5F1B9FB6")]
+    internal partial interface IJaggedIntArray
+    {
+        [return: MarshalUsing(CountElementName = nameof(length)),
+            MarshalUsing(ElementIndirectionDepth = 1, CountElementName = nameof(widths))]
+        int[][] Get(
+            [MarshalUsing(CountElementName = nameof(length))]
+            out int[] widths,
+            out int length);
+
+        int Get2(
+            [MarshalUsing(CountElementName = MarshalUsingAttribute.ReturnsCountValue),
+            MarshalUsing(ElementIndirectionDepth = 1, CountElementName = nameof(widths))]
+            out int[][] array,
+            [MarshalUsing(CountElementName = MarshalUsingAttribute.ReturnsCountValue)]
+            out int[] widths);
+
+        void Set(
+            [MarshalUsing(CountElementName = nameof(length)),
+            MarshalUsing(ElementIndirectionDepth = 1, CountElementName = nameof(widths))]
+            int[][] array,
+            [MarshalUsing(CountElementName = nameof(length))]
+            int[] widths,
+            int length);
+    }
+
+    [GeneratedComClass]
+    internal partial class IJaggedIntArrayImpl : IJaggedIntArray
+    {
+        int[][] _data = new int[][] { new int[] { 1, 2, 3 }, new int[] { 4, 5 }, new int[] { 6, 7, 8, 9 } };
+        int[] _widths = new int[] { 3, 2, 4 };
+        public int[][] Get(out int[] widths, out int length)
+        {
+            widths = _widths;
+            length = _data.Length;
+            return _data;
+        }
+        public int Get2(out int[][] array, out int[] widths)
+        {
+            array = _data;
+            widths = _widths;
+            return array.Length;
+        }
+        public void Set(int[][] array, int[] widths, int length)
+        {
+            _data = array;
+            _widths = widths;
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IRefStrings.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IRefStrings.cs
new file mode 100644
index 00000000000000..3a86b74a70b5c2
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IRefStrings.cs
@@ -0,0 +1,18 @@
+﻿// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Marshalling;
+
+namespace SharedTypes.ComInterfaces
+{
+    [GeneratedComInterface(StringMarshalling = System.Runtime.InteropServices.StringMarshalling.Utf8)]
+    [Guid(IID)]
+    internal partial interface IRefStrings
+    {
+        public const string IID = "5146B7DB-0588-469B-B8E5-B38090A2FC15";
+        void RefString(ref string value);
+        void InString(in string value);
+        void OutString(out string value);
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/ISafeHandles.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/ISafeHandles.cs
new file mode 100644
index 00000000000000..50a25b520939fb
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/ISafeHandles.cs
@@ -0,0 +1,19 @@
+﻿// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Marshalling;
+using Microsoft.Win32.SafeHandles;
+
+namespace SharedTypes.ComInterfaces
+{
+    [GeneratedComInterface(Options = ComInterfaceOptions.ComObjectWrapper), Guid("0A52B77C-E08B-4274-A1F4-1A2BF2C07E60")]
+    internal partial interface ISafeFileHandle
+    {
+        void Method(SafeFileHandle p);
+        void MethodIn(in SafeFileHandle p);
+        void MethodOut(out SafeFileHandle p);
+        void MethodRef(ref SafeFileHandle p);
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulCallerAllocatedBuffer.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulCallerAllocatedBuffer.cs
new file mode 100644
index 00000000000000..a585a5456b4039
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulCallerAllocatedBuffer.cs
@@ -0,0 +1,58 @@
+﻿// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Marshalling;
+
+namespace SharedTypes.ComInterfaces
+{
+    [GeneratedComInterface]
+    [Guid("4731FA5D-C103-4A22-87A1-58DCEDD4A9B3")]
+    internal partial interface IStatefulCallerAllocatedBufferMarshalling
+    {
+        void Method(StatefulCallerAllocatedBufferType param);
+        void MethodIn(in StatefulCallerAllocatedBufferType param);
+        void MethodOut(out StatefulCallerAllocatedBufferType param);
+        void MethodRef(ref StatefulCallerAllocatedBufferType param);
+        StatefulCallerAllocatedBufferType Return();
+        [PreserveSig]
+        StatefulCallerAllocatedBufferType ReturnPreserveSig();
+    }
+
+    [NativeMarshalling(typeof(StatefulCallerAllocatedBufferTypeMarshaller))]
+    internal class StatefulCallerAllocatedBufferType
+    {
+    }
+
+    [CustomMarshaller(typeof(StatefulCallerAllocatedBufferType), MarshalMode.Default, typeof(StatefulCallerAllocatedBufferTypeMarshaller))]
+    internal struct StatefulCallerAllocatedBufferTypeMarshaller
+    {
+        public static int BufferSize => 64;
+
+        public void FromManaged(StatefulCallerAllocatedBufferType managed, Span<byte> buffer)
+        {
+            throw new NotImplementedException();
+        }
+
+        public nint ToUnmanaged()
+        {
+            throw new NotImplementedException();
+        }
+
+        public void FromUnmanaged(nint unmanaged)
+        {
+            throw new NotImplementedException();
+        }
+
+        public StatefulCallerAllocatedBufferType ToManaged()
+        {
+            throw new NotImplementedException();
+        }
+
+        public void Free()
+        {
+            throw new NotImplementedException();
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulCollectionBlittableElement.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulCollectionBlittableElement.cs
new file mode 100644
index 00000000000000..e4df4476cfb7cc
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulCollectionBlittableElement.cs
@@ -0,0 +1,30 @@
+﻿// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Marshalling;
+
+namespace SharedTypes.ComInterfaces
+{
+    [GeneratedComInterface(), Guid("0A52B77C-E08B-4274-A1F4-1A2BF2C07E60")]
+    partial interface IStatefulCollectionBlittableElement
+    {
+        void Method(
+            [MarshalUsing(CountElementName = nameof(size))] StatefulCollection<int> p,
+            int size);
+        void MethodIn(
+            [MarshalUsing(CountElementName = nameof(size))] in StatefulCollection<int> pIn,
+            in int size);
+        void MethodRef(
+            [MarshalUsing(CountElementName = nameof(size))] ref StatefulCollection<int> pRef,
+            int size);
+        void MethodOut(
+            [MarshalUsing(CountElementName = nameof(size))] out StatefulCollection<int> pOut,
+            out int size);
+        [return: MarshalUsing(CountElementName = nameof(size))]
+        StatefulCollection<int> Return(int size);
+        [PreserveSig]
+        [return: MarshalUsing(CountElementName = nameof(size))]
+        StatefulCollection<int> ReturnPreserveSig(int size);
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulCollectionStatelessElement.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulCollectionStatelessElement.cs
new file mode 100644
index 00000000000000..d31c70856b6ebc
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulCollectionStatelessElement.cs
@@ -0,0 +1,57 @@
+﻿// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Marshalling;
+
+namespace SharedTypes.ComInterfaces
+{
+    [GeneratedComInterface(), Guid("0A52B77C-E08B-4274-A1F4-1A2BF2C07E60")]
+    partial interface IStatefulCollectionStatelessElement
+    {
+        void Method(
+            [MarshalUsing(CountElementName = nameof(size))] StatefulCollection<StatelessType> p,
+            int size);
+        void MethodIn(
+            [MarshalUsing(CountElementName = nameof(size))] in StatefulCollection<StatelessType> pIn,
+            in int size);
+        void MethodRef(
+            [MarshalUsing(CountElementName = nameof(size))] ref StatefulCollection<StatelessType> pRef,
+            int size);
+        void MethodOut(
+            [MarshalUsing(CountElementName = nameof(size))] out StatefulCollection<StatelessType> pOut,
+            out int size);
+        [return: MarshalUsing(CountElementName = nameof(size))]
+        StatefulCollection<StatelessType> Return(int size);
+        [PreserveSig]
+        [return: MarshalUsing(CountElementName = nameof(size))]
+        StatefulCollection<StatelessType> ReturnPreserveSig(int size);
+    }
+
+    [NativeMarshalling(typeof(StatefulCollectionMarshaller<,>))]
+    internal class StatefulCollection<T>
+    {
+    }
+
+    [ContiguousCollectionMarshaller]
+    [CustomMarshaller(typeof(StatefulCollection<>), MarshalMode.Default, typeof(StatefulCollectionMarshaller<,>.Default))]
+    static unsafe class StatefulCollectionMarshaller<T, TUnmanagedElement> where TUnmanagedElement : unmanaged
+    {
+        public ref struct Default
+        {
+            public byte* ToUnmanaged() => throw null;
+            public System.ReadOnlySpan<T> GetManagedValuesSource() => throw null;
+            public System.Span<TUnmanagedElement> GetUnmanagedValuesDestination() => throw null;
+
+            public void FromUnmanaged(byte* value) => throw null;
+            public System.Span<T> GetManagedValuesDestination(int numElements) => throw null;
+            public System.ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(int numElements) => throw null;
+
+            public void Free() => throw null;
+
+            public void FromManaged(StatefulCollection<T> managed) => throw null;
+
+            public StatefulCollection<T> ToManaged() => throw null;
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulFinallyMarshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulFinallyMarshalling.cs
new file mode 100644
index 00000000000000..70b9a4e78a0ac7
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulFinallyMarshalling.cs
@@ -0,0 +1,56 @@
+﻿// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Marshalling;
+
+namespace SharedTypes.ComInterfaces
+{
+    [GeneratedComInterface]
+    [Guid("4731FA5D-C103-4A22-87A1-58DCEDD4A9B3")]
+    internal partial interface IStatefulFinallyMarshalling
+    {
+        void Method(StatefulFinallyType param);
+        void MethodIn(in StatefulFinallyType param);
+        void MethodOut(out StatefulFinallyType param);
+        void MethodRef(ref StatefulFinallyType param);
+        StatefulFinallyType Return();
+        [PreserveSig]
+        StatefulFinallyType ReturnPreserveSig();
+    }
+
+    [NativeMarshalling(typeof(StatefulFinallyTypeMarshaller))]
+    internal class StatefulFinallyType
+    {
+    }
+
+    [CustomMarshaller(typeof(StatefulFinallyType), MarshalMode.Default, typeof(StatefulFinallyTypeMarshaller))]
+    internal struct StatefulFinallyTypeMarshaller
+    {
+        public void FromManaged(StatefulFinallyType managed)
+        {
+            throw new NotImplementedException();
+        }
+
+        public nint ToUnmanaged()
+        {
+            throw new NotImplementedException();
+        }
+
+        public void FromUnmanaged(nint unmanaged)
+        {
+            throw new NotImplementedException();
+        }
+
+        public StatefulFinallyType ToManagedFinally()
+        {
+            throw new NotImplementedException();
+        }
+
+        public void Free()
+        {
+            throw new NotImplementedException();
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulMarshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulMarshalling.cs
new file mode 100644
index 00000000000000..f84da40e9e2e00
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulMarshalling.cs
@@ -0,0 +1,57 @@
+﻿// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Marshalling;
+
+namespace SharedTypes.ComInterfaces
+{
+    [GeneratedComInterface]
+    [Guid("4731FA5D-C103-4A22-87A1-58DCEDD4A9B3")]
+    internal partial interface IStatefulMarshalling
+    {
+        void Method(StatefulType param);
+        void MethodIn(in StatefulType param);
+        void MethodOut(out StatefulType param);
+        void MethodRef(ref StatefulType param);
+        StatefulType Return();
+        [PreserveSig]
+        StatefulType ReturnPreserveSig();
+    }
+
+    [NativeMarshalling(typeof(StatefulTypeMarshaller))]
+    internal class StatefulType
+    {
+    }
+
+    [CustomMarshaller(typeof(StatefulType), MarshalMode.Default, typeof(StatefulTypeMarshaller))]
+    internal struct StatefulTypeMarshaller
+    {
+        public void FromManaged(StatefulType managed)
+        {
+            throw new System.NotImplementedException();
+        }
+
+        public nint ToUnmanaged()
+        {
+            throw new System.NotImplementedException();
+        }
+
+        public void FromUnmanaged(nint unmanaged)
+        {
+            throw new System.NotImplementedException();
+        }
+
+        public StatefulType ToManaged()
+        {
+            throw new System.NotImplementedException();
+        }
+
+        public void Free()
+        {
+            throw new System.NotImplementedException();
+        }
+
+        public void OnInvoked() { }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulPinnedMarshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulPinnedMarshalling.cs
new file mode 100644
index 00000000000000..1b5438cbdd6f25
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulPinnedMarshalling.cs
@@ -0,0 +1,61 @@
+﻿// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Marshalling;
+
+namespace SharedTypes.ComInterfaces
+{
+    [GeneratedComInterface]
+    [Guid("4731FA5D-C103-4A22-87A1-58DCEDD4A9B3")]
+    internal partial interface IStatefulPinnedMarshalling
+    {
+        void Method(StatefulPinnedType param);
+        void MethodIn(in StatefulPinnedType param);
+        void MethodOut(out StatefulPinnedType param);
+        void MethodRef(ref StatefulPinnedType param);
+        StatefulPinnedType Return();
+        [PreserveSig]
+        StatefulPinnedType ReturnPreserveSig();
+    }
+
+    [NativeMarshalling(typeof(StatefulPinnedTypeMarshaller))]
+    internal class StatefulPinnedType
+    {
+    }
+
+    [CustomMarshaller(typeof(StatefulPinnedType), MarshalMode.Default, typeof(StatefulPinnedTypeMarshaller))]
+    internal struct StatefulPinnedTypeMarshaller
+    {
+
+        public static int BufferSize => 64;
+        public ref int GetPinnableReference() => throw new System.NotImplementedException();
+        public void FromManaged(StatefulPinnedType managed, Span<byte> buffer)
+        {
+            throw new System.NotImplementedException();
+        }
+
+        public nint ToUnmanaged()
+        {
+            throw new System.NotImplementedException();
+        }
+
+        public void FromUnmanaged(nint unmanaged)
+        {
+            throw new System.NotImplementedException();
+        }
+
+        public StatefulPinnedType ToManaged()
+        {
+            throw new System.NotImplementedException();
+        }
+
+        public void Free()
+        {
+            throw new System.NotImplementedException();
+        }
+
+        public void OnInvoked() { }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCallerAllocateBufferMarshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCallerAllocateBufferMarshalling.cs
new file mode 100644
index 00000000000000..f5c3d4b7e2885c
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCallerAllocateBufferMarshalling.cs
@@ -0,0 +1,53 @@
+﻿// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Marshalling;
+
+namespace SharedTypes.ComInterfaces
+{
+    [GeneratedComInterface]
+    [Guid("4732FA5D-C105-4A23-87A7-58DCEDD4A9B3")]
+    internal partial interface IStatelessCallerAllocateBufferMarshalling
+    {
+        void Method([MarshalUsing(CountElementName = nameof(size))] StatelessCallerAllocatedBufferType param, int size);
+        void MethodIn([MarshalUsing(CountElementName = nameof(size))] in StatelessCallerAllocatedBufferType param, int size);
+        void MethodOut([MarshalUsing(CountElementName = nameof(size))] out StatelessCallerAllocatedBufferType param, int size);
+        void MethodRef([MarshalUsing(CountElementName = nameof(size))] ref StatelessCallerAllocatedBufferType param, int size);
+        StatelessCallerAllocatedBufferType Return();
+        [PreserveSig]
+        StatelessCallerAllocatedBufferType ReturnPreserveSig();
+    }
+
+    [GeneratedComClass]
+    internal partial class StatelessCallerAllocatedBufferMarshalling : IStatelessCallerAllocateBufferMarshalling
+    {
+        public void Method([MarshalUsing(CountElementName = "size")] StatelessCallerAllocatedBufferType param, int size) { }
+        public void MethodIn([MarshalUsing(CountElementName = "size")] in StatelessCallerAllocatedBufferType param, int size) { }
+        public void MethodOut([MarshalUsing(CountElementName = "size")] out StatelessCallerAllocatedBufferType param, int size) { param = new StatelessCallerAllocatedBufferType { I = 42 }; }
+        public void MethodRef([MarshalUsing(CountElementName = "size")] ref StatelessCallerAllocatedBufferType param, int size) { param = new StatelessCallerAllocatedBufferType { I = 200 }; }
+        public StatelessCallerAllocatedBufferType Return() => throw new NotImplementedException();
+        public StatelessCallerAllocatedBufferType ReturnPreserveSig() => throw new NotImplementedException();
+    }
+
+    [NativeMarshalling(typeof(StatelessCallerAllocatedBufferTypeMarshaller))]
+    internal class StatelessCallerAllocatedBufferType
+    {
+        public int I;
+    }
+
+    [CustomMarshaller(typeof(StatelessCallerAllocatedBufferType), MarshalMode.Default, typeof(StatelessCallerAllocatedBufferTypeMarshaller))]
+    internal static class StatelessCallerAllocatedBufferTypeMarshaller
+    {
+        public static int FreeCount { get; private set; }
+        public static int BufferSize => 64;
+        public static nint ConvertToUnmanaged(StatelessCallerAllocatedBufferType managed, Span<byte> buffer) => managed.I;
+
+        public static StatelessCallerAllocatedBufferType ConvertToManaged(nint unmanaged) => new StatelessCallerAllocatedBufferType { I = (int)unmanaged };
+
+        public static void Free(nint unmanaged) => FreeCount++;
+
+        public static nint ConvertToUnmanaged(StatelessCallerAllocatedBufferType managed) => managed.I;
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionBlittableElement.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionBlittableElement.cs
new file mode 100644
index 00000000000000..684352435e6269
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionBlittableElement.cs
@@ -0,0 +1,30 @@
+﻿// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Marshalling;
+
+namespace SharedTypes.ComInterfaces
+{
+    [GeneratedComInterface(), Guid("0A52B77C-E08B-4274-A1F4-1A2BF2C07E60")]
+    partial interface IStatelessCollectionBlittableElement
+    {
+        void Method(
+            [MarshalUsing(CountElementName = nameof(size))] StatelessCollection<int> p,
+            int size);
+        void MethodIn(
+            [MarshalUsing(CountElementName = nameof(size))] in StatelessCollection<int> pIn,
+            in int size);
+        void MethodRef(
+            [MarshalUsing(CountElementName = nameof(size))] ref StatelessCollection<int> pRef,
+            int size);
+        void MethodOut(
+            [MarshalUsing(CountElementName = nameof(size))] out StatelessCollection<int> pOut,
+            out int size);
+        [return: MarshalUsing(CountElementName = nameof(size))]
+        StatelessCollection<int> Return(int size);
+        [PreserveSig]
+        [return: MarshalUsing(CountElementName = nameof(size))]
+        StatelessCollection<int> ReturnPreserveSig(int size);
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionStatelessElement.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionStatelessElement.cs
new file mode 100644
index 00000000000000..ca6770fdf04401
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionStatelessElement.cs
@@ -0,0 +1,80 @@
+﻿// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Marshalling;
+
+namespace SharedTypes.ComInterfaces
+{
+    [GeneratedComInterface(), Guid("0A52B77C-E08B-4274-A1F4-1A2BF2C07E60")]
+    partial interface IStatelessCollectionStatelessElement
+    {
+        void Method(
+            [MarshalUsing(CountElementName = nameof(size))] StatelessCollection<StatelessType> p,
+            int size);
+
+        void MethodIn(
+            [MarshalUsing(CountElementName = nameof(size))] in StatelessCollection<StatelessType> pIn,
+            in int size);
+
+        void MethodRef(
+            [MarshalUsing(CountElementName = nameof(size))] ref StatelessCollection<StatelessType> pRef,
+            int size);
+
+        void MethodOut(
+            [MarshalUsing(CountElementName = nameof(size))] out StatelessCollection<StatelessType> pOut,
+            out int size);
+
+        [return: MarshalUsing(CountElementName = nameof(size))]
+        StatelessCollection<StatelessType> Return(int size);
+
+        [PreserveSig]
+        [return: MarshalUsing(CountElementName = nameof(size))]
+        StatelessCollection<StatelessType> ReturnPreserveSig(int size);
+    }
+
+    [NativeMarshalling(typeof(StatelessCollectionMarshaller<,>))]
+    internal class StatelessCollection<T>
+    {
+    }
+
+    [ContiguousCollectionMarshaller]
+    [CustomMarshaller(typeof(StatelessCollection<>), MarshalMode.Default, typeof(StatelessCollectionMarshaller<,>.Default))]
+    internal static unsafe class StatelessCollectionMarshaller<T, TUnmanagedElement> where TUnmanagedElement : unmanaged
+    {
+        internal static class Default
+        {
+            public static nint AllocateContainerForUnmanagedElements(StatelessCollection<T> managed, out int numElements)
+            {
+                throw new System.NotImplementedException();
+            }
+
+            public static StatelessCollection<T> AllocateContainerForManagedElements(nint unmanaged, int numElements)
+            {
+                throw new System.NotImplementedException();
+            }
+
+            public static System.ReadOnlySpan<T> GetManagedValuesSource(StatelessCollection<T> managed)
+            {
+                throw new System.NotImplementedException();
+            }
+
+            public static System.Span<TUnmanagedElement> GetUnmanagedValuesDestination(nint unmanaged, int numElements)
+            {
+                throw new System.NotImplementedException();
+            }
+
+            public static System.ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(nint unmanaged, int numElements)
+            {
+                throw new System.NotImplementedException();
+            }
+
+            public static System.Span<T> GetManagedValuesDestination(StatelessCollection<T> managed)
+            {
+                throw new System.NotImplementedException();
+            }
+
+            public static void Free(nint unmanaged) { }
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessFinallyMarshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessFinallyMarshalling.cs
new file mode 100644
index 00000000000000..6b0c57a1f37fba
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessFinallyMarshalling.cs
@@ -0,0 +1,50 @@
+﻿// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Marshalling;
+
+namespace SharedTypes.ComInterfaces
+{
+    [GeneratedComInterface]
+    [Guid("4732FA5D-C105-4A26-87A7-58DCEDD4A9B3")]
+    internal partial interface IStatelessFinallyMarshalling
+    {
+        void Method([MarshalUsing(CountElementName = nameof(size))] StatelessFinallyType param, int size);
+        void MethodIn([MarshalUsing(CountElementName = nameof(size))] in StatelessFinallyType param, int size);
+        void MethodOut([MarshalUsing(CountElementName = nameof(size))] out StatelessFinallyType param, int size);
+        void MethodRef([MarshalUsing(CountElementName = nameof(size))] ref StatelessFinallyType param, int size);
+        StatelessFinallyType Return();
+        [PreserveSig]
+        StatelessFinallyType ReturnPreserveSig();
+    }
+
+    [GeneratedComClass]
+    internal partial class StatelessFinallyMarshalling : IStatelessFinallyMarshalling
+    {
+        public void Method([MarshalUsing(CountElementName = "size")] StatelessFinallyType param, int size) { }
+        public void MethodIn([MarshalUsing(CountElementName = "size")] in StatelessFinallyType param, int size) { }
+        public void MethodOut([MarshalUsing(CountElementName = "size")] out StatelessFinallyType param, int size) { param = new StatelessFinallyType { I = 42 }; }
+        public void MethodRef([MarshalUsing(CountElementName = "size")] ref StatelessFinallyType param, int size) { param = new StatelessFinallyType { I = 200 }; }
+        public StatelessFinallyType Return() => throw new NotImplementedException();
+        public StatelessFinallyType ReturnPreserveSig() => throw new NotImplementedException();
+    }
+
+    [NativeMarshalling(typeof(StatelessFinallyTypeMarshaller))]
+    internal class StatelessFinallyType
+    {
+        public int I;
+    }
+
+    [CustomMarshaller(typeof(StatelessFinallyType), MarshalMode.Default, typeof(StatelessFinallyTypeMarshaller))]
+    internal static class StatelessFinallyTypeMarshaller
+    {
+        public static int FreeCount { get; private set; }
+        public static nint ConvertToUnmanaged(StatelessFinallyType managed) => managed.I;
+
+        public static StatelessFinallyType ConvertToManagedFinally(nint unmanaged) => new StatelessFinallyType { I = (int)unmanaged };
+
+        public static void Free(nint unmanaged) => FreeCount++;
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessMarshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessMarshalling.cs
new file mode 100644
index 00000000000000..1cb2f338216567
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessMarshalling.cs
@@ -0,0 +1,50 @@
+﻿// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Marshalling;
+
+namespace SharedTypes.ComInterfaces
+{
+    [GeneratedComInterface]
+    [Guid("4732FA5D-C105-4A23-87A7-58DCEDD4A9B3")]
+    internal partial interface IStatelessMarshalling
+    {
+        void Method([MarshalUsing(CountElementName = nameof(size))] StatelessType param, int size);
+        void MethodIn([MarshalUsing(CountElementName = nameof(size))] in StatelessType param, int size);
+        void MethodOut([MarshalUsing(CountElementName = nameof(size))] out StatelessType paramyBoi, int size);
+        void MethodRef([MarshalUsing(CountElementName = nameof(size))] ref StatelessType param, int size);
+        StatelessType Return();
+        [PreserveSig]
+        StatelessType ReturnPreserveSig();
+    }
+
+    [GeneratedComClass]
+    internal partial class StatelessMarshalling : IStatelessMarshalling
+    {
+        public void Method([MarshalUsing(CountElementName = "size")] StatelessType param, int size) { }
+        public void MethodIn([MarshalUsing(CountElementName = "size")] in StatelessType param, int size) { }
+        public void MethodOut([MarshalUsing(CountElementName = "size")] out StatelessType param, int size) { param = new StatelessType { I = 42 }; }
+        public void MethodRef([MarshalUsing(CountElementName = "size")] ref StatelessType param, int size) { param = new StatelessType { I = 200 }; }
+        public StatelessType Return() => throw new NotImplementedException();
+        public StatelessType ReturnPreserveSig() => throw new NotImplementedException();
+    }
+
+    [NativeMarshalling(typeof(StatelessTypeMarshaller))]
+    internal class StatelessType
+    {
+        public int I;
+    }
+
+    [CustomMarshaller(typeof(StatelessType), MarshalMode.Default, typeof(StatelessTypeMarshaller))]
+    internal static class StatelessTypeMarshaller
+    {
+        public static int FreeCount { get; private set; }
+        public static nint ConvertToUnmanaged(StatelessType managed) => managed.I;
+
+        public static StatelessType ConvertToManaged(nint unmanaged) => new StatelessType { I = (int)unmanaged };
+
+        public static void Free(nint unmanaged) => FreeCount++;
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessPinnedMarshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessPinnedMarshalling.cs
new file mode 100644
index 00000000000000..4419fc52c077cf
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessPinnedMarshalling.cs
@@ -0,0 +1,62 @@
+﻿// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Marshalling;
+
+namespace SharedTypes.ComInterfaces
+{
+    [GeneratedComInterface]
+    [Guid("4732FA5D-C105-4A23-87A7-58DCEDD4A9B3")]
+    internal partial interface IStatelessPinnedMarshalling
+    {
+        void Method([MarshalUsing(CountElementName = nameof(size))] StatelessPinnedType param, int size);
+        void MethodIn([MarshalUsing(CountElementName = nameof(size))] in StatelessPinnedType param, int size);
+        void MethodOut([MarshalUsing(CountElementName = nameof(size))] out StatelessPinnedType param, int size);
+        void MethodRef([MarshalUsing(CountElementName = nameof(size))] ref StatelessPinnedType param, int size);
+        StatelessPinnedType Return();
+        [PreserveSig]
+        StatelessPinnedType ReturnPreserveSig();
+    }
+
+    [GeneratedComClass]
+    internal partial class StatelessPinnedMarshalling : IStatelessPinnedMarshalling
+    {
+        public void Method([MarshalUsing(CountElementName = "size")] StatelessPinnedType param, int size) { }
+        public void MethodIn([MarshalUsing(CountElementName = "size")] in StatelessPinnedType param, int size) { }
+        public void MethodOut([MarshalUsing(CountElementName = "size")] out StatelessPinnedType param, int size) { param = new StatelessPinnedType { I = 42 }; }
+        public void MethodRef([MarshalUsing(CountElementName = "size")] ref StatelessPinnedType param, int size) { param = new StatelessPinnedType { I = 200 }; }
+        public StatelessPinnedType Return() => throw new NotImplementedException();
+        public StatelessPinnedType ReturnPreserveSig() => throw new NotImplementedException();
+    }
+
+    [NativeMarshalling(typeof(StatelessPinnedTypeMarshaller))]
+    internal class StatelessPinnedType
+    {
+        public int I;
+    }
+
+    internal struct StatelessPinnedStruct
+    {
+        public int I;
+    }
+
+    [CustomMarshaller(typeof(StatelessPinnedType), MarshalMode.Default, typeof(StatelessPinnedTypeMarshaller))]
+    internal static class StatelessPinnedTypeMarshaller
+    {
+        public static int FreeCount { get; private set; }
+        public static nint ConvertToUnmanaged(StatelessPinnedType managed) => managed.I;
+
+        public static StatelessPinnedType ConvertToManaged(nint unmanaged) => new StatelessPinnedType { I = (int)unmanaged };
+
+        static StatelessPinnedStruct _field;
+        public static ref StatelessPinnedStruct GetPinnableReference(StatelessPinnedType unmanaged)
+        {
+            _field = new StatelessPinnedStruct() { I = unmanaged.I };
+            return ref _field;
+        }
+
+        public static void Free(nint unmanaged) => FreeCount++;
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStringMarshallingOverride.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStringMarshallingOverride.cs
index cd7c8f620dc935..df956009fce8be 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStringMarshallingOverride.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStringMarshallingOverride.cs
@@ -2,20 +2,16 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System;
-using System.Collections.Generic;
-using System.Linq;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices.Marshalling;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace SharedTypes.ComInterfaces
 {
     [GeneratedComInterface(StringMarshalling = System.Runtime.InteropServices.StringMarshalling.Utf8)]
-    [Guid(_guid)]
+    [Guid(IID)]
     internal partial interface IStringMarshallingOverride
     {
-        public const string _guid = "5146B7DB-0588-469B-B8E5-B38090A2FC15";
+        public const string IID = "5146B7DB-0588-469B-B8E5-B38090A2FC15";
         string StringMarshallingUtf8(string input);
 
         [return: MarshalAs(UnmanagedType.LPWStr)]
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStringMarshallingOverrideDerived.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStringMarshallingOverrideDerived.cs
index 079db461a66bd8..5022d42d13930f 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStringMarshallingOverrideDerived.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStringMarshallingOverrideDerived.cs
@@ -2,20 +2,16 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Runtime.InteropServices.Marshalling;
 using System.Runtime.InteropServices;
-using System.Text;
-using System.Threading.Tasks;
+using System.Runtime.InteropServices.Marshalling;
 
 namespace SharedTypes.ComInterfaces
 {
     [GeneratedComInterface(StringMarshalling = StringMarshalling.Utf8)]
-    [Guid(_guid)]
+    [Guid(IID)]
     internal partial interface IStringMarshallingOverrideDerived : IStringMarshallingOverride
     {
-        public new const string _guid = "3AFFE3FD-D11E-4195-8250-0C73321977A0";
+        public new const string IID = "3AFFE3FD-D11E-4195-8250-0C73321977A0";
         string StringMarshallingUtf8_2(string input);
 
         [return: MarshalAs(UnmanagedType.LPWStr)]
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IUTF16Marshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IUTF16Marshalling.cs
index 2ef5534aa6b23d..1c123065a2ec1c 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IUTF16Marshalling.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IUTF16Marshalling.cs
@@ -7,7 +7,7 @@
 
 namespace SharedTypes.ComInterfaces
 {
-    [Guid(_guid)]
+    [Guid(IID)]
     [GeneratedComInterface(StringMarshalling = StringMarshalling.Utf16)]
     internal partial interface IUTF16Marshalling
     {
@@ -15,6 +15,6 @@ internal partial interface IUTF16Marshalling
 
         public void SetString(string value);
 
-        public const string _guid = "E11D5F3E-DD57-41A6-A59E-7D110551A760";
+        public const string IID = "E11D5F3E-DD57-41A6-A59E-7D110551A760";
     }
 }
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IUTF8Marshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IUTF8Marshalling.cs
index 2689425abd5065..08dbbdd5e68924 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IUTF8Marshalling.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IUTF8Marshalling.cs
@@ -7,7 +7,7 @@
 
 namespace SharedTypes.ComInterfaces
 {
-    [Guid(_guid)]
+    [Guid(IID)]
     [GeneratedComInterface(StringMarshalling = StringMarshalling.Utf8)]
     internal partial interface IUTF8Marshalling
     {
@@ -15,6 +15,6 @@ internal partial interface IUTF8Marshalling
 
         public void SetString(string value);
 
-        public const string _guid = "E11D5F3E-DD57-41A6-A59E-7D110551A760";
+        public const string IID = "E11D5F3E-DD57-41A6-A59E-7D110551A760";
     }
 }
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/MarshallingFails/ICollectionMarshallingFails.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/MarshallingFails/ICollectionMarshallingFails.cs
new file mode 100644
index 00000000000000..6e01be3d7e7da3
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/MarshallingFails/ICollectionMarshallingFails.cs
@@ -0,0 +1,38 @@
+﻿// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Marshalling;
+
+namespace SharedTypes.ComInterfaces.MarshallingFails
+{
+    [GeneratedComInterface]
+    [Guid("A4857395-06FB-4A6E-81DB-35461BE999C5")]
+    internal partial interface ICollectionMarshallingFails
+    {
+        [return: MarshalUsing(CountElementName = nameof(size))]
+        [return: MarshalUsing(typeof(ThrowOn4thElementMarshalled), ElementIndirectionDepth = 1)]
+        public int[] Get(out int size);
+        public void Set(
+            [MarshalUsing(CountElementName = nameof(size))]
+            [MarshalUsing(typeof(ThrowOn4thElementMarshalled), ElementIndirectionDepth = 1)]
+            int[] value, int size);
+    }
+
+    [GeneratedComClass]
+    internal partial class ICollectionMarshallingFailsImpl : ICollectionMarshallingFails
+    {
+        int[] _data = new[] { 1, 2, 3, 4, 5, 6, 7, 8 };
+        public int[] Get(out int size)
+        {
+            size = _data.Length;
+            return _data;
+        }
+        public void Set(int[] value, int size)
+        {
+            _data = new int[size];
+            value.CopyTo(_data, 0);
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/MarshallingFails/IJaggedIntArrayMarshallingFails.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/MarshallingFails/IJaggedIntArrayMarshallingFails.cs
new file mode 100644
index 00000000000000..a0d8e964b8f935
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/MarshallingFails/IJaggedIntArrayMarshallingFails.cs
@@ -0,0 +1,63 @@
+﻿// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Marshalling;
+
+namespace SharedTypes.ComInterfaces.MarshallingFails
+{
+    [GeneratedComInterface]
+    [Guid("9FA4A8A9-3D8F-48A8-B6FB-B45B5F1B9FB6")]
+    internal partial interface IJaggedIntArrayMarshallingFails
+    {
+        [return: MarshalUsing(CountElementName = nameof(length)),
+            MarshalUsing(ElementIndirectionDepth = 1, CountElementName = nameof(widths)),
+            MarshalUsing(typeof(ThrowOn4thElementMarshalled), ElementIndirectionDepth = 2)]
+        int[][] Get(
+            [MarshalUsing(CountElementName = nameof(length))]
+            out int[] widths,
+            out int length);
+
+        int Get2(
+            [MarshalUsing(CountElementName = MarshalUsingAttribute.ReturnsCountValue),
+            MarshalUsing(ElementIndirectionDepth = 1, CountElementName = nameof(widths)),
+            MarshalUsing(typeof(ThrowOn4thElementMarshalled), ElementIndirectionDepth = 2)]
+            out int[][] array,
+            [MarshalUsing(CountElementName = MarshalUsingAttribute.ReturnsCountValue)]
+            out int[] widths);
+
+        void Set(
+            [MarshalUsing(CountElementName = nameof(length)),
+            MarshalUsing(ElementIndirectionDepth = 1, CountElementName = nameof(widths)),
+            MarshalUsing(typeof(ThrowOn4thElementMarshalled), ElementIndirectionDepth = 2)]
+            int[][] array,
+            [MarshalUsing(CountElementName = nameof(length))]
+            int[] widths,
+            int length);
+    }
+
+    [GeneratedComClass]
+    internal partial class IJaggedIntArrayMarshallingFailsImpl : IJaggedIntArrayMarshallingFails
+    {
+        int[][] _data = new int[][] { new int[] { 1, 2, 3 }, new int[] { 4, 5 }, new int[] { 6, 7, 8, 9 } };
+        int[] _widths = new int[] { 3, 2, 4 };
+        public int[][] Get(out int[] widths, out int length)
+        {
+            widths = _widths;
+            length = _data.Length;
+            return _data;
+        }
+        public int Get2(out int[][] array, out int[] widths)
+        {
+            array = _data;
+            widths = _widths;
+            return array.Length;
+        }
+        public void Set(int[][] array, int[] widths, int length)
+        {
+            _data = array;
+            _widths = widths;
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/MarshallingFails/ThrowOn4thElementMarshalled.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/MarshallingFails/ThrowOn4thElementMarshalled.cs
new file mode 100644
index 00000000000000..99e01d95278e43
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/MarshallingFails/ThrowOn4thElementMarshalled.cs
@@ -0,0 +1,38 @@
+﻿// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Runtime.InteropServices.Marshalling;
+
+namespace SharedTypes.ComInterfaces.MarshallingFails
+{
+    [CustomMarshaller(typeof(int), MarshalMode.ElementIn, typeof(ThrowOn4thElementMarshalled))]
+    [CustomMarshaller(typeof(int), MarshalMode.ElementOut, typeof(ThrowOn4thElementMarshalled))]
+    internal static class ThrowOn4thElementMarshalled
+    {
+        static int _marshalledCount = 0;
+        static int _unmarshalledCount = 0;
+        public static int FreeCount { get; private set; }
+        public static nint ConvertToUnmanaged(int managed)
+        {
+            if (_marshalledCount++ == 3)
+            {
+                _marshalledCount = 0;
+                throw new ArgumentException("The element was the 4th element (with 0-based index 3)");
+            }
+            return managed;
+        }
+
+        public static int ConvertToManaged(nint unmanaged)
+        {
+            if (_unmarshalledCount++ == 3)
+            {
+                _unmarshalledCount = 0;
+                throw new ArgumentException("The element was the 4th element (with 0-based index 3)");
+            }
+            return (int)unmanaged;
+        }
+        public static void Free(nint unmanaged) => ++FreeCount;
+    }
+
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/SharedTypes.csproj b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/SharedTypes.csproj
index c68eadac7ca4b4..06fadd8571d0bd 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/SharedTypes.csproj
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/SharedTypes.csproj
@@ -9,6 +9,13 @@
     <Compile Include="$(CommonPath)DisableRuntimeMarshalling.cs" Link="Common\DisableRuntimeMarshalling.cs" />
   </ItemGroup>
 
+<Target Name="DisableComInterfaceGenerator"
+        BeforeTargets="CoreCompile">
+  <ItemGroup>
+  <Analyzer Remove="@(Analyzer)" Condition="'%(FileName)' == 'Microsoft.Interop.ComInterfaceGenerator'" />
+  </ItemGroup>
+</Target>
+
   <ItemGroup>
     <ProjectReference Include="..\..\Ancillary.Interop\Ancillary.Interop.csproj" />
   </ItemGroup>
