Warn when user code casts between runtime-based COM interop types and source-generate...
authorJeremy Koritzinsky <jekoritz@microsoft.com>
Tue, 13 Jun 2023 03:10:33 +0000 (20:10 -0700)
committerGitHub <noreply@github.com>
Tue, 13 Jun 2023 03:10:33 +0000 (20:10 -0700)
18 files changed:
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Analyzers/AnalyzerDiagnostics.cs
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Analyzers/RuntimeComApiUsageWithSourceGeneratedComAnalyzer.cs
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/Strings.resx
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.cs.xlf
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.de.xlf
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.es.xlf
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.fr.xlf
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.it.xlf
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.ja.xlf
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.ko.xlf
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.pl.xlf
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.pt-BR.xlf
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.ru.xlf
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.tr.xlf
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.zh-Hans.xlf
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.zh-Hant.xlf
src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/RuntimeComApiUsageWithSourceGeneratedComTests.cs
src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcProxyShimFactory.cs

index ad6a64e..d55e9e6 100644 (file)
@@ -13,7 +13,7 @@ namespace Microsoft.Interop.Analyzers
             public const string ConvertToGeneratedComInterface = Prefix + "1096";
             public const string AddGeneratedComClassAttribute = Prefix + "1097";
             public const string ComHostingDoesNotSupportGeneratedComInterface = Prefix + "1098";
-            public const string RuntimeComApisDoNotSupportSourceGeneratedCom = Prefix + "1099";
+            public const string RuntimeComAndGeneratedComDoNotMix = Prefix + "1099";
         }
 
         public static class Metadata
@@ -61,12 +61,22 @@ namespace Microsoft.Interop.Analyzers
 
         public static readonly DiagnosticDescriptor RuntimeComApisDoNotSupportSourceGeneratedCom =
             new DiagnosticDescriptor(
-                Ids.RuntimeComApisDoNotSupportSourceGeneratedCom,
+                Ids.RuntimeComAndGeneratedComDoNotMix,
                 GetResourceString(nameof(SR.RuntimeComApisDoNotSupportSourceGeneratedComTitle)),
                 GetResourceString(nameof(SR.RuntimeComApisDoNotSupportSourceGeneratedComMessage)),
                 Category,
                 DiagnosticSeverity.Warning,
                 isEnabledByDefault: true,
                 description: GetResourceString(nameof(SR.RuntimeComApisDoNotSupportSourceGeneratedComDescription)));
+
+        public static readonly DiagnosticDescriptor CastsBetweenRuntimeComAndSourceGeneratedComNotSupported =
+            new DiagnosticDescriptor(
+                Ids.RuntimeComAndGeneratedComDoNotMix,
+                GetResourceString(nameof(SR.CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedTitle)),
+                GetResourceString(nameof(SR.CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedMessage)),
+                Category,
+                DiagnosticSeverity.Warning,
+                isEnabledByDefault: true,
+                description: GetResourceString(nameof(SR.CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedDescription)));
     }
 }
index 41b9c65..6cbb11e 100644 (file)
@@ -18,7 +18,7 @@ namespace Microsoft.Interop.Analyzers
     [DiagnosticAnalyzer(LanguageNames.CSharp)]
     public class RuntimeComApiUsageWithSourceGeneratedComAnalyzer : DiagnosticAnalyzer
     {
-        public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(RuntimeComApisDoNotSupportSourceGeneratedCom);
+        public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(RuntimeComApisDoNotSupportSourceGeneratedCom, CastsBetweenRuntimeComAndSourceGeneratedComNotSupported);
 
         public override void Initialize(AnalysisContext context)
         {
@@ -130,6 +130,60 @@ namespace Microsoft.Interop.Analyzers
                     }
                 }, OperationKind.Invocation);
 
+                var getObjectForIUnknown = marshalType.GetMembers("GetObjectForIUnknown")[0];
+
+                context.RegisterOperationAction(context =>
+                {
+                    var operation = (IConversionOperation)context.Operation;
+                    if (operation.Type is INamedTypeSymbol { IsComImport: true })
+                    {
+                        IOperation operand = operation.Operand;
+                        if (operand is IConversionOperation { Type.SpecialType: SpecialType.System_Object } objConversion)
+                        {
+                            operand = objConversion.Operand;
+                        }
+                        foreach (var recognizer in sourceGeneratedComRecognizers)
+                        {
+                            if (recognizer(operand.Type))
+                            {
+                                context.ReportDiagnostic(
+                                    Diagnostic.Create(
+                                        CastsBetweenRuntimeComAndSourceGeneratedComNotSupported,
+                                        operation.Syntax.GetLocation()));
+                                break;
+                            }
+                        }
+                    }
+
+                    foreach (var recognizer in sourceGeneratedComRecognizers)
+                    {
+                        if (recognizer(operation.Type))
+                        {
+                            IOperation operand = operation.Operand;
+                            if (operand is IConversionOperation { Type.SpecialType: SpecialType.System_Object } objConversion)
+                            {
+                                operand = objConversion.Operand;
+                            }
+                            if (operand.Type is INamedTypeSymbol { IsComImport: true })
+                            {
+                                context.ReportDiagnostic(
+                                    Diagnostic.Create(
+                                        CastsBetweenRuntimeComAndSourceGeneratedComNotSupported,
+                                            operation.Syntax.GetLocation()));
+                                break;
+                            }
+                            else if (operand is IInvocationOperation invocation && invocation.TargetMethod.Equals(getObjectForIUnknown, SymbolEqualityComparer.Default))
+                            {
+                                context.ReportDiagnostic(
+                                    Diagnostic.Create(
+                                        CastsBetweenRuntimeComAndSourceGeneratedComNotSupported,
+                                            operation.Syntax.GetLocation()));
+                                break;
+                            }
+                        }
+                    }
+                }, OperationKind.Conversion);
+
                 static Func<IInvocationOperation, (ITypeSymbol Type, Location location)?> CreateArgumentTypeLookup(int ordinal) => invocation => invocation.GetArgumentByOrdinal(ordinal).Value switch
                 {
                     IConversionOperation conversion => (conversion.Operand.Type, conversion.Operand.Syntax.GetLocation()),
index 5bbe8eb..46df116 100644 (file)
@@ -1,17 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
 <root>
-  <!--
-    Microsoft ResX Schema
-
+  <!-- 
+    Microsoft ResX Schema 
+    
     Version 2.0
-
-    The primary goals of this format is to allow a simple XML format
-    that is mostly human readable. The generation and parsing of the
-    various data types are done through the TypeConverter classes
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
     associated with the data types.
-
+    
     Example:
-
+    
     ... ado.net/XML headers & schema ...
     <resheader name="resmimetype">text/microsoft-resx</resheader>
     <resheader name="version">2.0</resheader>
         <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
         <comment>This is a comment</comment>
     </data>
-
-    There are any number of "resheader" rows that contain simple
+                
+    There are any number of "resheader" rows that contain simple 
     name/value pairs.
-
-    Each data row contains a name, and value. The row also contains a
-    type or mimetype. Type corresponds to a .NET class that support
-    text/value conversion through the TypeConverter architecture.
-    Classes that don't support this are serialized and stored with the
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
     mimetype set.
-
-    The mimetype is used for serialized objects, and tells the
-    ResXResourceReader how to depersist the object. This is currently not
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
     extensible. For a given mimetype the value must be set accordingly:
-
-    Note - application/x-microsoft.net.object.binary.base64 is the format
-    that the ResXResourceWriter will generate, however the reader can
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
     read any of the formats listed below.
-
+    
     mimetype: application/x-microsoft.net.object.binary.base64
-    value   : The object must be serialized with
+    value   : The object must be serialized with 
             : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
             : and then encoded with base64 encoding.
-
+    
     mimetype: application/x-microsoft.net.object.soap.base64
-    value   : The object must be serialized with
+    value   : The object must be serialized with 
             : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
             : and then encoded with base64 encoding.
 
     mimetype: application/x-microsoft.net.object.bytearray.base64
-    value   : The object must be serialized into a byte array
+    value   : The object must be serialized into a byte array 
             : using a System.ComponentModel.TypeConverter
             : and then encoded with base64 encoding.
     -->
   <data name="ConvertComInterfaceMayProduceInvalidCode" xml:space="preserve">
     <value>Converting this interface to use 'GeneratedComInterfaceAttribute' may produce invalid code and may require additional work</value>
   </data>
-</root>
+  <data name="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedDescription" xml:space="preserve">
+    <value>Casting between a 'ComImport' type and a source-generated COM type is not supported and will fail at runtime</value>
+  </data>
+  <data name="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedMessage" xml:space="preserve">
+    <value>Casting between a 'ComImport' type and a source-generated COM type is not supported</value>
+  </data>
+  <data name="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedTitle" xml:space="preserve">
+    <value>Casting between a 'ComImport' type and a source-generated COM type is not supported</value>
+  </data>
+</root>
\ No newline at end of file
index ab079fb..c38a0fc 100644 (file)
         <target state="needs-review-translation">Základnímu rozhraní COM se nepodařilo vygenerovat zdroj. ComInterfaceGenerator nevygeneruje zdroj pro toto rozhraní.</target>
         <note />
       </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedDescription">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported and will fail at runtime</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported and will fail at runtime</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedMessage">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedTitle">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceDescription">
         <source>.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</source>
         <target state="new">.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</target>
index 1e9474a..39f481a 100644 (file)
         <target state="needs-review-translation">Die Basis-COM-Schnittstelle konnte die Quelle nicht generieren. ComInterfaceGenerator generiert keine Quelle für diese Schnittstelle.</target>
         <note />
       </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedDescription">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported and will fail at runtime</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported and will fail at runtime</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedMessage">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedTitle">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceDescription">
         <source>.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</source>
         <target state="new">.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</target>
index 40d06bb..a934567 100644 (file)
         <target state="needs-review-translation">La interfaz COM base no pudo generar el origen. ComInterfaceGenerator no generará el origen para esta interfaz.</target>
         <note />
       </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedDescription">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported and will fail at runtime</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported and will fail at runtime</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedMessage">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedTitle">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceDescription">
         <source>.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</source>
         <target state="new">.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</target>
index aead2ae..a51c404 100644 (file)
         <target state="needs-review-translation">L’interface COM de base n’a pas pu générer la source. ComInterfaceGenerator ne génère pas de source pour cette interface.</target>
         <note />
       </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedDescription">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported and will fail at runtime</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported and will fail at runtime</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedMessage">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedTitle">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceDescription">
         <source>.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</source>
         <target state="new">.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</target>
index 811c87b..2470a2d 100644 (file)
         <target state="needs-review-translation">L'interfaccia COM di base non è riuscita a generare l'origine. ComInterfaceGenerator non genererà l'origine per questa interfaccia.</target>
         <note />
       </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedDescription">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported and will fail at runtime</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported and will fail at runtime</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedMessage">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedTitle">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceDescription">
         <source>.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</source>
         <target state="new">.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</target>
index 8e01e4c..94a2cb0 100644 (file)
         <target state="needs-review-translation">ベース COM インターフェイスはソースを生成できませんでした。ComInterfaceGenerator は、このインターフェイスのソースを生成しません。</target>
         <note />
       </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedDescription">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported and will fail at runtime</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported and will fail at runtime</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedMessage">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedTitle">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceDescription">
         <source>.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</source>
         <target state="new">.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</target>
index 318be73..76d63ef 100644 (file)
         <target state="needs-review-translation">기본 COM 인터페이스에서 원본을 생성하지 못했습니다. ComInterfaceGenerator는 이 인터페이스에 대한 원본을 생성하지 않습니다.</target>
         <note />
       </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedDescription">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported and will fail at runtime</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported and will fail at runtime</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedMessage">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedTitle">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceDescription">
         <source>.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</source>
         <target state="new">.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</target>
index 85eff7c..f36f6b3 100644 (file)
         <target state="needs-review-translation">Podstawowy interfejs COM nie może wygenerować źródła. Program ComInterfaceGenerator nie wygeneruje źródła dla tego interfejsu.</target>
         <note />
       </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedDescription">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported and will fail at runtime</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported and will fail at runtime</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedMessage">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedTitle">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceDescription">
         <source>.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</source>
         <target state="new">.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</target>
index 4c4ffbf..7225bb3 100644 (file)
         <target state="needs-review-translation">A interface COM base falhou ao gerar a fonte. ComInterfaceGenerator não irá gerar fonte para esta interface.</target>
         <note />
       </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedDescription">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported and will fail at runtime</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported and will fail at runtime</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedMessage">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedTitle">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceDescription">
         <source>.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</source>
         <target state="new">.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</target>
index 0fc1b09..8c98a4e 100644 (file)
         <target state="needs-review-translation">Базовому COM-интерфейсу не удалось создать источник. ComInterfaceGenerator не будет создавать источник для этого интерфейса.</target>
         <note />
       </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedDescription">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported and will fail at runtime</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported and will fail at runtime</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedMessage">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedTitle">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceDescription">
         <source>.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</source>
         <target state="new">.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</target>
index 6c35945..27f831d 100644 (file)
         <target state="needs-review-translation">Temel COM arabirimi kaynak oluşturamadı. ComInterfaceGenerator bu arabirim için kaynak oluşturamaz.</target>
         <note />
       </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedDescription">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported and will fail at runtime</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported and will fail at runtime</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedMessage">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedTitle">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceDescription">
         <source>.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</source>
         <target state="new">.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</target>
index f67a6f5..8cd7d5a 100644 (file)
         <target state="needs-review-translation">基本 COM 接口无法生成源。ComInterfaceGenerator 不会为此接口生成源。</target>
         <note />
       </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedDescription">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported and will fail at runtime</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported and will fail at runtime</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedMessage">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedTitle">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceDescription">
         <source>.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</source>
         <target state="new">.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</target>
index 12fd284..7ccf2a3 100644 (file)
         <target state="needs-review-translation">基底 COM 介面無法產生來源。ComInterfaceGenerator 不會產生此介面的來源。</target>
         <note />
       </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedDescription">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported and will fail at runtime</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported and will fail at runtime</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedMessage">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="CastsBetweenRuntimeComAndSourceGeneratedComNotSupportedTitle">
+        <source>Casting between a 'ComImport' type and a source-generated COM type is not supported</source>
+        <target state="new">Casting between a 'ComImport' type and a source-generated COM type is not supported</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ComHostingDoesNotSupportGeneratedComInterfaceDescription">
         <source>.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</source>
         <target state="new">.NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'.</target>
index 19b90f9..25246b3 100644 (file)
@@ -1,6 +1,8 @@
 // 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.Threading;
 using System.Threading.Tasks;
 using Xunit;
 using VerifyCS = Microsoft.Interop.UnitTests.Verifiers.CSharpAnalyzerVerifier<
@@ -46,7 +48,7 @@ namespace ComInterfaceGenerator.Unit.Tests
                }
                """;
 
-            await VerifyCS.VerifyAnalyzerAsync(source);
+            await VerifyAnalyzerAsync(source);
         }
 
         [Fact]
@@ -84,7 +86,7 @@ namespace ComInterfaceGenerator.Unit.Tests
                }
                """;
 
-            await VerifyCS.VerifyAnalyzerAsync(source);
+            await VerifyAnalyzerAsync(source);
         }
 
         [Fact]
@@ -122,7 +124,7 @@ namespace ComInterfaceGenerator.Unit.Tests
                }
                """;
 
-            await VerifyCS.VerifyAnalyzerAsync(source);
+            await VerifyAnalyzerAsync(source);
         }
 
         [Fact]
@@ -160,7 +162,7 @@ namespace ComInterfaceGenerator.Unit.Tests
                }
                """;
 
-            await VerifyCS.VerifyAnalyzerAsync(source);
+            await VerifyAnalyzerAsync(source);
         }
 
         [Fact]
@@ -204,7 +206,7 @@ namespace ComInterfaceGenerator.Unit.Tests
                 }
                 """;
 
-            await VerifyCS.VerifyAnalyzerAsync(source);
+            await VerifyAnalyzerAsync(source);
         }
 
         [Fact]
@@ -266,7 +268,7 @@ namespace ComInterfaceGenerator.Unit.Tests
                 }
                 """;
 
-            await VerifyCS.VerifyAnalyzerAsync(source);
+            await VerifyAnalyzerAsync(source);
         }        
 
         [Fact]
@@ -298,7 +300,7 @@ namespace ComInterfaceGenerator.Unit.Tests
                 }
                 """;
 
-            await VerifyCS.VerifyAnalyzerAsync(source);
+            await VerifyAnalyzerAsync(source);
         }
 
         [Fact]
@@ -336,7 +338,7 @@ namespace ComInterfaceGenerator.Unit.Tests
                 }
                 """;
 
-            await VerifyCS.VerifyAnalyzerAsync(source);
+            await VerifyAnalyzerAsync(source);
         }
 
         [Fact]
@@ -374,7 +376,7 @@ namespace ComInterfaceGenerator.Unit.Tests
                 }
                 """;
 
-            await VerifyCS.VerifyAnalyzerAsync(source);
+            await VerifyAnalyzerAsync(source);
         }
 
         [Fact]
@@ -421,7 +423,101 @@ namespace ComInterfaceGenerator.Unit.Tests
                }
                """;
 
-            await VerifyCS.VerifyAnalyzerAsync(source);
+            await VerifyAnalyzerAsync(source);
+        }
+
+        [Fact]
+        public async Task CastsBetweenComImportAndGeneratedComTypes()
+        {
+            string source = """
+              using System.Runtime.InteropServices;
+              using System.Runtime.InteropServices.Marshalling;
+      
+              [GeneratedComInterface]
+              [Guid("0B7171CD-04A3-41B6-AD10-FE86D52197DD")]
+              public interface I
+              {
+              }
+      
+              [GeneratedComClass]
+              public class C : I
+              {
+              }
+
+              [ComImport]
+              [Guid("0BADBF92-749A-44DB-9DA0-C8E2EEC783E2")]
+              public interface J
+              {
+              }
+      
+              public static class Program
+              {
+                  public static void Foo(I i)
+                  {
+                      J j = [|(J)i|];
+                      i = [|(I)j|];
+                  }
+
+                  public static void Foo(C c)
+                  {
+                      J j = [|(J)c|];
+                      c = [|(C)j|];
+                  }
+
+                  public static void Foo(ComObject c)
+                  {
+                      J j = [|(J)(object)c|];
+                      c = [|(ComObject)(object)j|];
+                  }
+              }
+              """;
+
+            await VerifyAnalyzerAsync(source);
+        }
+
+
+
+        [Fact]
+        public async Task GetObjectForIUnknown()
+        {
+            string source = """
+                using System.Runtime.InteropServices;
+                using System.Runtime.InteropServices.Marshalling;
+      
+                [GeneratedComInterface]
+                [Guid("0B7171CD-04A3-41B6-AD10-FE86D52197DD")]
+                public interface I
+                {
+                }
+      
+                [GeneratedComClass]
+                public class C : I
+                {
+                }
+      
+                public static class Program
+                {
+                    public static void Foo(nint i)
+                    {
+                        I io = [|(I)Marshal.GetObjectForIUnknown(i)|];
+                        C co = [|(C)Marshal.GetObjectForIUnknown(i)|];
+                        ComObject obj = [|(ComObject)Marshal.GetObjectForIUnknown(i)|];
+                    }
+                }
+                """;
+
+            await VerifyAnalyzerAsync(source);
+        }
+
+        private Task VerifyAnalyzerAsync(string source)
+        {
+            var test = new VerifyCS.Test
+            {
+                TestCode = source,
+                MarkupOptions = Microsoft.CodeAnalysis.Testing.MarkupOptions.UseFirstDescriptor
+            };
+
+            return test.RunAsync(CancellationToken.None);
         }
     }
 }
index 8400cad..ef42dc2 100644 (file)
@@ -260,7 +260,7 @@ internal sealed partial class DtcProxyShimFactory
         out OletxTransactionIsolationLevel isolationLevel,
         out TransactionShim transactionShim)
     {
-        var cloner = (ITransactionCloner)transactionNative;
+        var cloner = (ITransactionCloner)TransactionInterop.GetITransactionFromIDtcTransaction(transactionNative);
         cloner.CloneWithCommitDisabled(out ITransaction transaction);
 
         SetupTransaction(transaction, managedIdentifier, out transactionIdentifier, out isolationLevel, out transactionShim);