Update 'Utils.IsComObject' to use 'Marshal.IsComObject' since CAS is no longer supported in .NET Core (#7344)

A comment from the existing `Utils.IsComObject` mentions that: "We can't use System.Runtime.InteropServices.Marshal.IsComObject(obj) since it doesn't work in partial trust."

Partial trust is a concept of Code Access Security (CAS)/Security-Transparent. CAS and Security-Transparent are no longer supported in .NET Core, so we should use `Marshal.IsComObject` instead.
This commit is contained in:
Dongbo Wang
2018-07-26 09:59:07 -07:00
committed by GitHub
parent 1583318d72
commit 41111a15e6
3 changed files with 27 additions and 38 deletions
@@ -1345,43 +1345,26 @@ namespace System.Management.Automation
internal static readonly char[] PathSearchTrimEnd = { (char)0x9, (char)0xA, (char)0xB, (char)0xC, (char)0xD, (char)0x20, (char)0x85, (char)0xA0 };
}
#if !UNIX
// This is to reduce the runtime overhead of the feature query
private static readonly Type ComObjectType = typeof(object).Assembly.GetType("System.__ComObject");
#endif
internal static bool IsComObject(PSObject psObject)
{
#if UNIX
return false;
#else
if (psObject == null) { return false; }
object obj = PSObject.Base(psObject);
return IsComObject(obj);
#endif
}
/// <summary>
/// A COM object could be directly of the type 'System.__ComObject', or it could be a strongly typed RWC,
/// whose specific type derives from 'System.__ComObject'.
/// A strongly typed RWC can be created via the 'new' operation with a Primary Interop Assembly (PIA).
/// For example, with the PIA 'Microsoft.Office.Interop.Excel', you can write the following code:
/// var excelApp = new Microsoft.Office.Interop.Excel.Application();
/// Type type = excelApp.GetType();
/// Type comObjectType = typeof(object).Assembly.GetType("System.__ComObject");
/// Console.WriteLine("excelApp type: {0}", type.FullName);
/// Console.WriteLine("Is __ComObject assignable from? {0}", comObjectType.IsAssignableFrom(type));
/// and the results are:
/// excelApp type: Microsoft.Office.Interop.Excel.ApplicationClass
/// Is __ComObject assignable from? True
/// </summary>
internal static bool IsComObject(object obj)
{
#if UNIX
return false;
#else
// We can't use System.Runtime.InteropServices.Marshal.IsComObject(obj) since it doesn't work in partial trust.
//
// There could be strongly typed RWCs whose type is not 'System.__ComObject', but the more specific type should
// derive from 'System.__ComObject'. The strongly typed RWCs can be created with 'new' operation via the Primay
// Interop Assembly (PIA).
// For example, with the PIA 'Microsoft.Office.Interop.Excel', you can write the following code:
// var excelApp = new Microsoft.Office.Interop.Excel.Application();
// Type type = excelApp.GetType();
// Type comObjectType = typeof(object).Assembly.GetType("System.__ComObject");
// Console.WriteLine("excelApp type: {0}", type.FullName);
// Console.WriteLine("Is __ComObject assignable from? {0}", comObjectType.IsAssignableFrom(type));
// and the results are:
// excelApp type: Microsoft.Office.Interop.Excel.ApplicationClass
// Is __ComObject assignable from? True
return obj != null && ComObjectType.IsAssignableFrom(obj.GetType());
return obj != null && Marshal.IsComObject(obj);
#endif
}
}
@@ -499,7 +499,7 @@ namespace System.Management.Automation.Language
typeof(VariableOps).GetMethod(nameof(VariableOps.SetVariableValue), staticFlags);
internal static readonly MethodInfo Utils_IsComObject =
typeof(Utils).GetMethod(nameof(Utils.IsComObject), staticFlags, binder: null, types: new Type[] {typeof(object)}, modifiers: null);
typeof(Utils).GetMethod(nameof(Utils.IsComObject), staticFlags);
internal static readonly MethodInfo ClassOps_ValidateSetProperty =
typeof(ClassOps).GetMethod(nameof(ClassOps.ValidateSetProperty), staticPublicFlags);
@@ -14,6 +14,7 @@ using System.Management.Automation.Internal;
using System.Management.Automation.Runspaces;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
@@ -619,7 +620,7 @@ namespace System.Management.Automation.Language
GetRestrictions(target))).WriteToDebugLog(this);
}
if (Utils.IsComObject(targetValue))
if (Marshal.IsComObject(targetValue))
{
// Pretend that all com objects are enumerable, even if they aren't. We do this because it's technically impossible
// to know if a com object is enumerable without just trying to cast it to IEnumerable. We could generate a rule like:
@@ -715,7 +716,12 @@ namespace System.Management.Automation.Language
private static IEnumerator NotEnumerableRule(CallSite site, object obj)
{
if (!(obj is PSObject) && !(obj is IEnumerable) && !(obj is IEnumerator) && !(obj is DataTable) && !Utils.IsComObject(obj))
if (obj == null)
{
return null;
}
if (!(obj is PSObject) && !(obj is IEnumerable) && !(obj is IEnumerator) && !(obj is DataTable) && !Marshal.IsComObject(obj))
{
return null;
}
@@ -4988,7 +4994,7 @@ namespace System.Management.Automation.Language
if (target.Value is PSObject && (PSObject.Base(target.Value) != target.Value))
{
Object baseObject = PSObject.Base(target.Value);
if (baseObject != null && Utils.IsComObject(baseObject))
if (baseObject != null && Marshal.IsComObject(baseObject))
{
// We unwrap only if the 'base' is a COM object. It's unnecessary to unwrap in other cases,
// especially in the case of strings, we would lose instance members on the PSObject.
@@ -5859,7 +5865,7 @@ namespace System.Management.Automation.Language
(value.Value is PSObject && (PSObject.Base(value.Value) != value.Value)))
{
Object baseObject = PSObject.Base(target.Value);
if (baseObject != null && Utils.IsComObject(baseObject))
if (baseObject != null && Marshal.IsComObject(baseObject))
{
// We unwrap only if the 'base' of 'target' is a COM object. It's unnecessary to unwrap in other cases,
// especially in the case that 'target' is a string, we would lose instance members on the PSObject.
@@ -6380,7 +6386,7 @@ namespace System.Management.Automation.Language
args.Any(mo => mo.Value is PSObject && (PSObject.Base(mo.Value) != mo.Value)))
{
Object baseObject = PSObject.Base(target.Value);
if (baseObject != null && Utils.IsComObject(baseObject))
if (baseObject != null && Marshal.IsComObject(baseObject))
{
// We unwrap only if the 'base' of 'target' is a COM object. It's unnecessary to unwrap in other cases,
// especially in the case that 'target' is a string, we would lose instance members on the PSObject.