mirror of
https://github.com/aphrody-labs/PowerShell.git
synced 2026-10-17 20:56:02 +00:00
127 lines
4.6 KiB
C#
127 lines
4.6 KiB
C#
/********************************************************************++
|
|||
|
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
|
--********************************************************************/
|
||
|
|
|
||
|
|
#if !SILVERLIGHT // ComObject
|
||
|
|
#if !CLR2
|
||
|
|
using System.Linq.Expressions;
|
||
|
|
#else
|
||
|
|
using Microsoft.Scripting.Ast;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
using System;
|
||
|
|
using System.Collections.Generic;
|
||
|
|
using System.Diagnostics;
|
||
|
|
using System.Reflection;
|
||
|
|
using System.Runtime.InteropServices;
|
||
|
|
using System.Security;
|
||
|
|
using System.Security.Permissions;
|
||
|
|
using System.Dynamic;
|
||
|
|
|
||
|
|
namespace System.Management.Automation.ComInterop {
|
||
|
|
/// <summary>
|
||
|
|
/// This is a helper class for runtime-callable-wrappers of COM instances. We create one instance of this type
|
||
|
|
/// for every generic RCW instance.
|
||
|
|
/// </summary>
|
||
|
|
internal class ComObject : IDynamicMetaObjectProvider {
|
||
|
|
/// <summary>
|
||
|
|
/// The runtime-callable wrapper
|
||
|
|
/// </summary>
|
||
|
|
private readonly object _rcw;
|
||
|
|
|
||
|
|
internal ComObject(object rcw) {
|
||
|
|
Debug.Assert(ComObject.IsComObject(rcw));
|
||
|
|
_rcw = rcw;
|
||
|
|
}
|
||
|
|
|
||
|
|
internal object RuntimeCallableWrapper {
|
||
|
|
get {
|
||
|
|
return _rcw;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private readonly static object _ComObjectInfoKey = new object();
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// This is the factory method to get the ComObject corresponding to an RCW
|
||
|
|
/// </summary>
|
||
|
|
/// <returns></returns>
|
||
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")]
|
||
|
|
public static ComObject ObjectToComObject(object rcw) {
|
||
|
|
Debug.Assert(ComObject.IsComObject(rcw));
|
||
|
|
|
||
|
|
// Marshal.Get/SetComObjectData has a LinkDemand for UnmanagedCode which will turn into
|
||
|
|
// a full demand. We could avoid this by making this method SecurityCritical
|
||
|
|
object data = Marshal.GetComObjectData(rcw, _ComObjectInfoKey);
|
||
|
|
if (data != null) {
|
||
|
|
return (ComObject)data;
|
||
|
|
}
|
||
|
|
|
||
|
|
lock (_ComObjectInfoKey) {
|
||
|
|
data = Marshal.GetComObjectData(rcw, _ComObjectInfoKey);
|
||
|
|
if (data != null) {
|
||
|
|
return (ComObject)data;
|
||
|
|
}
|
||
|
|
|
||
|
|
ComObject comObjectInfo = CreateComObject(rcw);
|
||
|
|
if (!Marshal.SetComObjectData(rcw, _ComObjectInfoKey, comObjectInfo)) {
|
||
|
|
throw Error.SetComObjectDataFailed();
|
||
|
|
}
|
||
|
|
|
||
|
|
return comObjectInfo;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Expression that unwraps ComObject
|
||
|
|
internal static MemberExpression RcwFromComObject(Expression comObject) {
|
||
|
|
Debug.Assert(comObject != null && typeof(ComObject).IsAssignableFrom(comObject.Type), "must be ComObject");
|
||
|
|
|
||
|
|
return Expression.Property(
|
||
|
|
Helpers.Convert(comObject, typeof(ComObject)),
|
||
|
|
typeof(ComObject).GetProperty("RuntimeCallableWrapper", BindingFlags.NonPublic | BindingFlags.Instance)
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Expression that finds or creates a ComObject that corresponds to given Rcw
|
||
|
|
internal static MethodCallExpression RcwToComObject(Expression rcw) {
|
||
|
|
return Expression.Call(
|
||
|
|
typeof(ComObject).GetMethod("ObjectToComObject"),
|
||
|
|
Helpers.Convert(rcw, typeof(object))
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static ComObject CreateComObject(object rcw) {
|
||
|
|
IDispatch dispatchObject = rcw as IDispatch;
|
||
|
|
if (dispatchObject != null) {
|
||
|
|
// We can do method invocations on IDispatch objects
|
||
|
|
return new IDispatchComObject(dispatchObject);
|
||
|
|
}
|
||
|
|
|
||
|
|
// There is not much we can do in this case
|
||
|
|
return new ComObject(rcw);
|
||
|
|
}
|
||
|
|
|
||
|
|
internal virtual IList<string> GetMemberNames(bool dataOnly) {
|
||
|
|
return Utils.EmptyArray<string>();
|
||
|
|
}
|
||
|
|
|
||
|
|
internal virtual IList<KeyValuePair<string, object>> GetMembers(IEnumerable<string> names) {
|
||
|
|
return Utils.EmptyArray<KeyValuePair<string, object>>();
|
||
|
|
}
|
||
|
|
|
||
|
|
DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter) {
|
||
|
|
return new ComFallbackMetaObject(parameter, BindingRestrictions.Empty, this);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static readonly Type ComObjectType = typeof(object).Assembly.GetType("System.__ComObject");
|
||
|
|
|
||
|
|
internal static bool IsComObject(object obj) {
|
||
|
|
// we can't use System.Runtime.InteropServices.Marshal.IsComObject(obj) since it doesn't work in partial trust
|
||
|
|
return obj != null && ComObjectType.IsAssignableFrom(obj.GetType());
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif
|
||
|
|
|