From: Jeremy Koritzinsky Date: Mon, 23 Sep 2019 23:30:46 +0000 (-0700) Subject: Error out clearly when trying to use COM objects with the DLR. (dotnet/corefx#40075) X-Git-Tag: submit/tizen/20210909.063632~11031^2~422 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=38120d9da1a57d6e39cb627a31e441b1b0f01cc6;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Error out clearly when trying to use COM objects with the DLR. (dotnet/corefx#40075) * Throw an exception in the dynamic binder when trying to dynamically resolve a COM object without an enabled COM binder. * Add test for exception throw on dynamic usage with COM. * Update test to validate the change in each binder. * PR Feedback. * Add missing using. Commit migrated from https://github.com/dotnet/corefx/commit/5ed05b311925509d3cd4b6938d4935ca31cdaf92 --- diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/BinderHelper.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/BinderHelper.cs index 67c7a43..57a33b1 100644 --- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/BinderHelper.cs +++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/BinderHelper.cs @@ -11,6 +11,7 @@ using System.Linq.Expressions; using System.Runtime.InteropServices; using System.Reflection; using System.Numerics.Hashing; +using Microsoft.CSharp.RuntimeBinder.Errors; namespace Microsoft.CSharp.RuntimeBinder { @@ -182,7 +183,6 @@ namespace Microsoft.CSharp.RuntimeBinder return obj != null && Marshal.IsComObject(obj); } -#if ENABLECOMBINDER ///////////////////////////////////////////////////////////////////////////////// // Try to determine if this object represents a WindowsRuntime object - i.e. it either @@ -210,7 +210,7 @@ namespace Microsoft.CSharp.RuntimeBinder return false; } -#endif + ///////////////////////////////////////////////////////////////////////////////// private static bool IsTransparentProxy(object obj) @@ -513,5 +513,15 @@ namespace Microsoft.CSharp.RuntimeBinder return true; } + +#if !ENABLECOMBINDER + internal static void ThrowIfUsingDynamicCom(DynamicMetaObject target) + { + if (!BinderHelper.IsWindowsRuntimeObject(target) && target.LimitType.IsCOMObject) + { + throw ErrorHandling.Error(ErrorCode.ERR_DynamicBindingComUnsupported); + } + } +#endif } } diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpConvertBinder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpConvertBinder.cs index 455fee1..fa45efb 100644 --- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpConvertBinder.cs +++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpConvertBinder.cs @@ -7,6 +7,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Dynamic; using System.Numerics.Hashing; +using Microsoft.CSharp.RuntimeBinder.Errors; using Microsoft.CSharp.RuntimeBinder.Semantics; namespace Microsoft.CSharp.RuntimeBinder @@ -121,7 +122,10 @@ namespace Microsoft.CSharp.RuntimeBinder { return com; } +#else + BinderHelper.ThrowIfUsingDynamicCom(target); #endif + BinderHelper.ValidateBindArgument(target, nameof(target)); return BinderHelper.Bind(this, _binder, new[] { target }, null, errorSuggestion); } diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpGetIndexBinder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpGetIndexBinder.cs index d0d69c7..b36e838 100644 --- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpGetIndexBinder.cs +++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpGetIndexBinder.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Dynamic; +using Microsoft.CSharp.RuntimeBinder.Errors; using Microsoft.CSharp.RuntimeBinder.Semantics; namespace Microsoft.CSharp.RuntimeBinder @@ -89,11 +90,14 @@ namespace Microsoft.CSharp.RuntimeBinder { #if ENABLECOMBINDER DynamicMetaObject com; - if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryBindGetIndex(this, target, indexes, out com)) + if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryConvert(this, target, out com)) { return com; } +#else + BinderHelper.ThrowIfUsingDynamicCom(target); #endif + BinderHelper.ValidateBindArgument(target, nameof(target)); BinderHelper.ValidateBindArgument(indexes, nameof(indexes)); return BinderHelper.Bind(this, _binder, BinderHelper.Cons(target, indexes), _argumentInfo, errorSuggestion); diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpGetMemberBinder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpGetMemberBinder.cs index b300da8..a088414 100644 --- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpGetMemberBinder.cs +++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpGetMemberBinder.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Dynamic; using System.Numerics.Hashing; +using Microsoft.CSharp.RuntimeBinder.Errors; using Microsoft.CSharp.RuntimeBinder.Semantics; namespace Microsoft.CSharp.RuntimeBinder @@ -104,11 +105,14 @@ namespace Microsoft.CSharp.RuntimeBinder { #if ENABLECOMBINDER DynamicMetaObject com; - if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryBindGetMember(this, target, out com, ResultIndexed)) + if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryConvert(this, target, out com)) { return com; } +#else + BinderHelper.ThrowIfUsingDynamicCom(target); #endif + BinderHelper.ValidateBindArgument(target, nameof(target)); return BinderHelper.Bind(this, _binder, new[] { target }, _argumentInfo, errorSuggestion); } diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpInvokeBinder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpInvokeBinder.cs index 0adc77a..6f1fca3 100644 --- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpInvokeBinder.cs +++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpInvokeBinder.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Dynamic; using System.Numerics.Hashing; +using Microsoft.CSharp.RuntimeBinder.Errors; using Microsoft.CSharp.RuntimeBinder.Semantics; namespace Microsoft.CSharp.RuntimeBinder @@ -101,13 +102,15 @@ namespace Microsoft.CSharp.RuntimeBinder public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { #if ENABLECOMBINDER - DynamicMetaObject com; - if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryBindInvoke(this, target, args, out com)) + if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryConvert(this, target, out com)) { return com; } +#else + BinderHelper.ThrowIfUsingDynamicCom(target); #endif + BinderHelper.ValidateBindArgument(target, nameof(target)); BinderHelper.ValidateBindArgument(args, nameof(args)); return BinderHelper.Bind(this, _binder, BinderHelper.Cons(target, args), _argumentInfo, errorSuggestion); diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpInvokeMemberBinder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpInvokeMemberBinder.cs index 3cb08b3..1da115c 100644 --- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpInvokeMemberBinder.cs +++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpInvokeMemberBinder.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Dynamic; using System.Numerics.Hashing; +using Microsoft.CSharp.RuntimeBinder.Errors; using Microsoft.CSharp.RuntimeBinder.Semantics; namespace Microsoft.CSharp.RuntimeBinder @@ -115,11 +116,14 @@ namespace Microsoft.CSharp.RuntimeBinder { #if ENABLECOMBINDER DynamicMetaObject com; - if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryBindInvokeMember(this, target, args, out com)) + if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryConvert(this, target, out com)) { return com; } +#else + BinderHelper.ThrowIfUsingDynamicCom(target); #endif + BinderHelper.ValidateBindArgument(target, nameof(target)); BinderHelper.ValidateBindArgument(args, nameof(args)); return BinderHelper.Bind(this, _binder, BinderHelper.Cons(target, args), _argumentInfo, errorSuggestion); diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpSetIndexBinder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpSetIndexBinder.cs index 71c3bd5..2779431 100644 --- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpSetIndexBinder.cs +++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpSetIndexBinder.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Dynamic; using System.Numerics.Hashing; +using Microsoft.CSharp.RuntimeBinder.Errors; using Microsoft.CSharp.RuntimeBinder.Semantics; namespace Microsoft.CSharp.RuntimeBinder @@ -109,11 +110,14 @@ namespace Microsoft.CSharp.RuntimeBinder { #if ENABLECOMBINDER DynamicMetaObject com; - if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryBindSetIndex(this, target, indexes, value, out com)) + if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryConvert(this, target, out com)) { return com; } +#else + BinderHelper.ThrowIfUsingDynamicCom(target); #endif + BinderHelper.ValidateBindArgument(target, nameof(target)); BinderHelper.ValidateBindArgument(indexes, nameof(indexes)); BinderHelper.ValidateBindArgument(value, nameof(value)); diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpSetMemberBinder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpSetMemberBinder.cs index 66315db..1fbd07c 100644 --- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpSetMemberBinder.cs +++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpSetMemberBinder.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Dynamic; using System.Numerics.Hashing; +using Microsoft.CSharp.RuntimeBinder.Errors; using Microsoft.CSharp.RuntimeBinder.Semantics; namespace Microsoft.CSharp.RuntimeBinder @@ -109,11 +110,14 @@ namespace Microsoft.CSharp.RuntimeBinder { #if ENABLECOMBINDER DynamicMetaObject com; - if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryBindSetMember(this, target, value, out com)) + if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryConvert(this, target, out com)) { return com; } +#else + BinderHelper.ThrowIfUsingDynamicCom(target); #endif + BinderHelper.ValidateBindArgument(target, nameof(target)); BinderHelper.ValidateBindArgument(value, nameof(value)); return BinderHelper.Bind(this, _binder, new[] { target, value }, _argumentInfo, errorSuggestion); diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Errors/ErrorCode.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Errors/ErrorCode.cs index d0003f4..a386666 100644 --- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Errors/ErrorCode.cs +++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Errors/ErrorCode.cs @@ -64,6 +64,7 @@ namespace Microsoft.CSharp.RuntimeBinder.Errors ERR_NamedArgumentUsedInPositional = 1744, ERR_BadNamedArgumentForDelegateInvoke = 1746, ERR_NonInvocableMemberCalled = 1955, - ERR_BadNonTrailingNamedArgument = 8323 + ERR_BadNonTrailingNamedArgument = 8323, + ERR_DynamicBindingComUnsupported = 8365 } } diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Errors/ErrorFacts.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Errors/ErrorFacts.cs index a339a97..ad0f121 100644 --- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Errors/ErrorFacts.cs +++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Errors/ErrorFacts.cs @@ -191,7 +191,9 @@ namespace Microsoft.CSharp.RuntimeBinder.Errors case ErrorCode.ERR_BadNonTrailingNamedArgument: codeStr = SR.BadNonTrailingNamedArgument; break; - + case ErrorCode.ERR_DynamicBindingComUnsupported: + codeStr = SR.DynamicBindingComUnsupported; + break; default: // means missing resources match the code entry Debug.Fail("Missing resources for the error " + code.ToString()); diff --git a/src/libraries/Microsoft.CSharp/src/Resources/Strings.resx b/src/libraries/Microsoft.CSharp/src/Resources/Strings.resx index ecde81c..ea1e5ad 100644 --- a/src/libraries/Microsoft.CSharp/src/Resources/Strings.resx +++ b/src/libraries/Microsoft.CSharp/src/Resources/Strings.resx @@ -329,6 +329,9 @@ anonymous method + + The C# runtime binder cannot dynamically resolve members on COM Runtime Callable Wrappers. + <error> diff --git a/src/libraries/Microsoft.CSharp/tests/RuntimeBinderTests.cs b/src/libraries/Microsoft.CSharp/tests/RuntimeBinderTests.cs index 38bfa96..6d81430 100644 --- a/src/libraries/Microsoft.CSharp/tests/RuntimeBinderTests.cs +++ b/src/libraries/Microsoft.CSharp/tests/RuntimeBinderTests.cs @@ -6,6 +6,7 @@ using System; using System.Collections; using System.ComponentModel; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using Xunit; // IVT to "Microsoft.CSharp.RuntimeBinder.Binder", just to use IVT in a test (see: InternalsVisibleToTest below) @@ -49,7 +50,7 @@ namespace Microsoft.CSharp.RuntimeBinder.Tests public void GenericNameMatchesPredefined() { dynamic d = 3; - dynamic v = new Value {Quantity = d}; + dynamic v = new Value { Quantity = d }; dynamic r = v.Quantity; Assert.Equal(3, r); dynamic h = new Holder(); @@ -391,5 +392,64 @@ namespace Microsoft.CSharp.RuntimeBinder.Tests Func target2 = getter.Target; Assert.Equal(message, Assert.Throws(() => target2(getter, null)).Message); } + + // This is not the defined COM interface for IKnownFolderManager. + // We need a registered COM interface and CoClass to validate the behavior with dynamic and COM. + // The real IKnownFolderManager interface is available on Windows Vista+, so it is on all platforms that we're testing. + [ComImport] + [Guid("8BE2D872-86AA-4d47-B776-32CCA40C7018")] + interface Not_IKnownFolderManager + { + void MethodCall(); + + int this[int i] { get; set; } + + int Property { get; set; } + } + + [CoClass(typeof(KnownFolderManagerClass))] + [ComImport] + [Guid("8BE2D872-86AA-4d47-B776-32CCA40C7018")] + interface KnownFolderManager : Not_IKnownFolderManager { } + + [Guid("4df0c730-df9d-4ae3-9153-aa6b82e9795a")] + class KnownFolderManagerClass { } + + [Fact] + [PlatformSpecific(TestPlatforms.Windows)] + [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)] + public void DynamicComThrowsException() + { + Assert.Throws(() => + { + var a = new { Manager = new KnownFolderManagerClass() }; + dynamic d = a; + d.Manager.MethodCall(); + }); + Assert.Throws(() => + { + var a = new { Manager = new KnownFolderManagerClass() }; + dynamic d = a; + return d.Manager[0]; + }); + Assert.Throws(() => + { + var a = new { Manager = new KnownFolderManagerClass() }; + dynamic d = a; + d.Manager[0] = 1; + }); + Assert.Throws(() => + { + var a = new { Manager = new KnownFolderManagerClass() }; + dynamic d = a; + d.Manager.Property = 1; + }); + Assert.Throws(() => + { + var a = new { Manager = new KnownFolderManagerClass() }; + dynamic d = a; + d.Manager.Property = 1; + }); + } } }