Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

23
mcs/class/dlr/ChangeLog Normal file
View File

@@ -0,0 +1,23 @@
2010-04-06 Marek Safar <marek.safar@gmail.com>
* Updated to r46640.
2009-11-26 Marek Safar <marek.safar@gmail.com>
* Updated to r35702.
2009-11-09 Marek Safar <marek.safar@gmail.com>
* Makefile: Add dist only Makefile.
2009-10-23 Marek Safar <marek.safar@gmail.com>
* Updated to r33356.
2009-08-04 Marek Safar <marek.safar@gmail.com>
* Updated to r26623.
2009-07-02 Marek Safar <marek.safar@gmail.com>
* Initial import, revision 25679.

15
mcs/class/dlr/Makefile Normal file
View File

@@ -0,0 +1,15 @@
thisdir = class/dlr
SUBDIRS =
include ../../build/rules.make
DISTFILES = \
Runtime/Microsoft.Dynamic/*.cs \
Runtime/Microsoft.Scripting.Core/Actions/*.cs \
Runtime/Microsoft.Scripting.Core/Ast/*.cs \
Runtime/Microsoft.Scripting.Core/Compiler/*.cs \
Runtime/Microsoft.Scripting.Core/Utils/*.cs
all-local install-local clean-local test-local run-test-local run-test-ondotnet-local uninstall-local doc-update-local csproj-local:
dist-local: dist-default

View File

@@ -0,0 +1,61 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Microsoft Public License. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Microsoft Public License, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Microsoft Public License.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System; using Microsoft;
#if !SILVERLIGHT
#if CODEPLEX_40
using System.Linq.Expressions;
#else
using Microsoft.Linq.Expressions;
#endif
#if CODEPLEX_40
namespace System.Dynamic {
#else
namespace Microsoft.Scripting {
#endif
/// <summary>
/// ArgBuilder provides an argument value used by the MethodBinder. One ArgBuilder exists for each
/// physical parameter defined on a method.
///
/// Contrast this with ParameterWrapper which represents the logical argument passed to the method.
/// </summary>
internal abstract class ArgBuilder {
/// <summary>
/// Provides the Expression which provides the value to be passed to the argument.
/// </summary>
internal abstract Expression Marshal(Expression parameter);
/// <summary>
/// Provides the Expression which provides the value to be passed to the argument.
/// This method is called when result is intended to be used ByRef.
/// </summary>
internal virtual Expression MarshalToRef(Expression parameter) {
return Marshal(parameter);
}
/// <summary>
/// Provides an Expression which will update the provided value after a call to the method.
/// May return null if no update is required.
/// </summary>
internal virtual Expression UnmarshalFromRef(Expression newValue) {
return newValue;
}
}
}
#endif

View File

@@ -0,0 +1,82 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Microsoft Public License. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Microsoft Public License, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Microsoft Public License.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
#define DEBUG
using System; using Microsoft;
using System.Collections.Generic;
using System.Diagnostics;
#if CODEPLEX_40
namespace System.Dynamic {
#else
namespace Microsoft.Scripting {
#endif
internal static class Assert {
internal static Exception Unreachable {
get {
Debug.Assert(false, "Unreachable");
return new InvalidOperationException("Code supposed to be unreachable");
}
}
[Conditional("DEBUG")]
internal static void NotNull(object var) {
Debug.Assert(var != null);
}
[Conditional("DEBUG")]
internal static void NotNull(object var1, object var2) {
Debug.Assert(var1 != null && var2 != null);
}
[Conditional("DEBUG")]
internal static void NotNull(object var1, object var2, object var3) {
Debug.Assert(var1 != null && var2 != null && var3 != null);
}
[Conditional("DEBUG")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1025:ReplaceRepetitiveArgumentsWithParamsArray")]
internal static void NotNull(object var1, object var2, object var3, object var4) {
Debug.Assert(var1 != null && var2 != null && var3 != null && var4 != null);
}
[Conditional("DEBUG")]
internal static void NotEmpty(string str) {
Debug.Assert(!String.IsNullOrEmpty(str));
}
[Conditional("DEBUG")]
internal static void NotEmpty<T>(ICollection<T> array) {
Debug.Assert(array != null && array.Count > 0);
}
[Conditional("DEBUG")]
internal static void NotNullItems<T>(IEnumerable<T> items) where T : class {
Debug.Assert(items != null);
foreach (object item in items) {
Debug.Assert(item != null);
}
}
[Conditional("DEBUG")]
internal static void IsTrue(Func<bool> predicate) {
ContractUtils.RequiresNotNull(predicate, "predicate");
Debug.Assert(predicate());
}
}
}

View File

@@ -0,0 +1,72 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Microsoft Public License. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Microsoft Public License, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Microsoft Public License.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System; using Microsoft;
#if !SILVERLIGHT // ComObject
using System.Collections.Generic;
using System.Diagnostics;
#if CODEPLEX_40
using System.Linq.Expressions;
#else
using Microsoft.Linq.Expressions;
#endif
using System.Runtime.CompilerServices;
#if !CODEPLEX_40
using Microsoft.Runtime.CompilerServices;
#endif
using System.Runtime.InteropServices;
#if CODEPLEX_40
using System.Dynamic.Utils;
#else
using Microsoft.Scripting.Utils;
#endif
#if CODEPLEX_40
namespace System.Dynamic {
#else
namespace Microsoft.Scripting {
#endif
internal sealed class BoolArgBuilder : SimpleArgBuilder {
internal BoolArgBuilder(Type parameterType)
: base(parameterType) {
Debug.Assert(parameterType == typeof(bool));
}
internal override Expression MarshalToRef(Expression parameter) {
// parameter ? -1 : 0
return Expression.Condition(
Marshal(parameter),
Expression.Constant((Int16)(-1)),
Expression.Constant((Int16)0)
);
}
internal override Expression UnmarshalFromRef(Expression value) {
//parameter = temp != 0
return base.UnmarshalFromRef(
Expression.NotEqual(
value,
Expression.Constant((Int16)0)
)
);
}
}
}
#endif

View File

@@ -0,0 +1,138 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Microsoft Public License. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Microsoft Public License, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Microsoft Public License.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System; using Microsoft;
#if !SILVERLIGHT // ComObject
#if CODEPLEX_40
using System.Linq.Expressions;
#else
using Microsoft.Linq.Expressions;
#endif
using System.Runtime.CompilerServices;
#if !CODEPLEX_40
using Microsoft.Runtime.CompilerServices;
#endif
using System.Security;
using System.Security.Permissions;
#if CODEPLEX_40
namespace System.Dynamic {
#else
namespace Microsoft.Scripting {
#endif
internal sealed class BoundDispEvent : DynamicObject {
private object _rcw;
private Guid _sourceIid;
private int _dispid;
internal BoundDispEvent(object rcw, Guid sourceIid, int dispid) {
_rcw = rcw;
_sourceIid = sourceIid;
_dispid = dispid;
}
/// <summary>
/// Provides the implementation of performing AddAssign and SubtractAssign binary operations.
/// </summary>
/// <param name="binder">The binder provided by the call site.</param>
/// <param name="handler">The handler for the operation.</param>
/// <param name="result">The result of the operation.</param>
/// <returns>true if the operation is complete, false if the call site should determine behavior.</returns>
public override bool TryBinaryOperation(BinaryOperationBinder binder, object handler, out object result) {
if (binder.Operation == ExpressionType.AddAssign) {
result = InPlaceAdd(handler);
return true;
}
if (binder.Operation == ExpressionType.SubtractAssign) {
result = InPlaceSubtract(handler);
return true;
}
result = null;
return false;
}
private static void VerifyHandler(object handler) {
if (handler is Delegate && handler.GetType() != typeof(Delegate)) {
return; // delegate
}
if (handler is IDynamicMetaObjectProvider) {
return; // IDMOP
}
throw Error.UnsupportedHandlerType();
}
/// <summary>
/// Adds a handler to an event.
/// </summary>
/// <param name="handler">The handler to be added.</param>
/// <returns>The original event with handler added.</returns>
#if CLR2
[SecurityCritical, SecurityTreatAsSafe]
#else
[SecuritySafeCritical]
#endif
private object InPlaceAdd(object handler) {
ContractUtils.RequiresNotNull(handler, "handler");
VerifyHandler(handler);
//
// Demand Full Trust to proceed with the operation.
//
new PermissionSet(PermissionState.Unrestricted).Demand();
ComEventSink comEventSink = ComEventSink.FromRuntimeCallableWrapper(_rcw, _sourceIid, true);
comEventSink.AddHandler(_dispid, handler);
return this;
}
/// <summary>
/// Removes handler from the event.
/// </summary>
/// <param name="handler">The handler to be removed.</param>
/// <returns>The original event with handler removed.</returns>
#if CLR2
[SecurityCritical, SecurityTreatAsSafe]
#else
[SecuritySafeCritical]
#endif
private object InPlaceSubtract(object handler) {
ContractUtils.RequiresNotNull(handler, "handler");
VerifyHandler(handler);
//
// Demand Full Trust to proceed with the operation.
//
new PermissionSet(PermissionState.Unrestricted).Demand();
ComEventSink comEventSink = ComEventSink.FromRuntimeCallableWrapper(_rcw, _sourceIid, false);
if (comEventSink != null) {
comEventSink.RemoveHandler(_dispid, handler);
}
return this;
}
}
}
#endif

View File

@@ -0,0 +1,55 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Microsoft Public License. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Microsoft Public License, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Microsoft Public License.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System; using Microsoft;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
#if CODEPLEX_40
namespace System.Dynamic {
#else
namespace Microsoft.Scripting {
#endif
internal static class CollectionExtensions {
internal static T[] RemoveFirst<T>(this T[] array) {
T[] result = new T[array.Length - 1];
Array.Copy(array, 1, result, 0, result.Length);
return result;
}
internal static T[] AddFirst<T>(this IList<T> list, T item) {
T[] res = new T[list.Count + 1];
res[0] = item;
list.CopyTo(res, 1);
return res;
}
internal static T[] ToArray<T>(this IList<T> list) {
T[] res = new T[list.Count];
list.CopyTo(res, 0);
return res;
}
internal static T[] AddLast<T>(this IList<T> list, T item) {
T[] res = new T[list.Count + 1];
list.CopyTo(res, 0);
res[list.Count] = item;
return res;
}
}
}

View File

@@ -0,0 +1,446 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Microsoft Public License. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Microsoft Public License, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Microsoft Public License.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System; using Microsoft;
#if !SILVERLIGHT
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
#if CODEPLEX_40
using System.Linq.Expressions;
#else
using Microsoft.Linq.Expressions;
#endif
using System.Security;
using System.Security.Permissions;
#if CODEPLEX_40
[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "System.Dynamic")]
#else
[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "Microsoft.Scripting")]
#endif
#if CODEPLEX_40
namespace System.Dynamic {
#else
namespace Microsoft.Scripting {
#endif
/// <summary>
/// Provides helper methods to bind COM objects dynamically.
/// </summary>
#if MICROSOFT_DYNAMIC
public
#else
internal
#endif
static class ComBinder {
/// <summary>
/// Determines if an object is a COM object.
/// </summary>
/// <param name="value">The object to test.</param>
/// <returns>true if the object is a COM object, false otherwise.</returns>
public static bool IsComObject(object value) {
return ComObject.IsComObject(value);
}
/// <summary>
/// Tries to perform binding of the dynamic get member operation.
/// </summary>
/// <param name="binder">An instance of the <see cref="GetMemberBinder"/> that represents the details of the dynamic operation.</param>
/// <param name="instance">The target of the dynamic operation. </param>
/// <param name="result">The new <see cref="DynamicMetaObject"/> representing the result of the binding.</param>
/// <param name="delayInvocation">true if member evaluation may be delayed.</param>
/// <returns>true if operation was bound successfully; otherwise, false.</returns>
#if CLR2
[SecurityCritical, SecurityTreatAsSafe]
#else
[SecuritySafeCritical]
#endif
public static bool TryBindGetMember(GetMemberBinder binder, DynamicMetaObject instance, out DynamicMetaObject result, bool delayInvocation) {
ContractUtils.RequiresNotNull(binder, "binder");
ContractUtils.RequiresNotNull(instance, "instance");
if (TryGetMetaObject(ref instance)) {
//
// Demand Full Trust to proceed with the binding.
//
new PermissionSet(PermissionState.Unrestricted).Demand();
var comGetMember = new ComGetMemberBinder(binder, delayInvocation);
result = instance.BindGetMember(comGetMember);
if (result.Expression.Type.IsValueType) {
result = new DynamicMetaObject(
Expression.Convert(result.Expression, typeof(object)),
result.Restrictions
);
}
return true;
} else {
result = null;
return false;
}
}
/// <summary>
/// Tries to perform binding of the dynamic get member operation.
/// </summary>
/// <param name="binder">An instance of the <see cref="GetMemberBinder"/> that represents the details of the dynamic operation.</param>
/// <param name="instance">The target of the dynamic operation. </param>
/// <param name="result">The new <see cref="DynamicMetaObject"/> representing the result of the binding.</param>
/// <returns>true if operation was bound successfully; otherwise, false.</returns>
public static bool TryBindGetMember(GetMemberBinder binder, DynamicMetaObject instance, out DynamicMetaObject result) {
return TryBindGetMember(binder, instance, out result, false);
}
/// <summary>
/// Tries to perform binding of the dynamic set member operation.
/// </summary>
/// <param name="binder">An instance of the <see cref="SetMemberBinder"/> that represents the details of the dynamic operation.</param>
/// <param name="instance">The target of the dynamic operation.</param>
/// <param name="value">The <see cref="DynamicMetaObject"/> representing the value for the set member operation.</param>
/// <param name="result">The new <see cref="DynamicMetaObject"/> representing the result of the binding.</param>
/// <returns>true if operation was bound successfully; otherwise, false.</returns>
#if CLR2
[SecurityCritical, SecurityTreatAsSafe]
#else
[SecuritySafeCritical]
#endif
public static bool TryBindSetMember(SetMemberBinder binder, DynamicMetaObject instance, DynamicMetaObject value, out DynamicMetaObject result) {
ContractUtils.RequiresNotNull(binder, "binder");
ContractUtils.RequiresNotNull(instance, "instance");
ContractUtils.RequiresNotNull(value, "value");
if (TryGetMetaObject(ref instance)) {
//
// Demand Full Trust to proceed with the binding.
//
new PermissionSet(PermissionState.Unrestricted).Demand();
result = instance.BindSetMember(binder, value);
return true;
} else {
result = null;
return false;
}
}
/// <summary>
/// Tries to perform binding of the dynamic invoke operation.
/// </summary>
/// <param name="binder">An instance of the <see cref="InvokeBinder"/> that represents the details of the dynamic operation.</param>
/// <param name="instance">The target of the dynamic operation. </param>
/// <param name="args">An array of <see cref="DynamicMetaObject"/> instances - arguments to the invoke member operation.</param>
/// <param name="result">The new <see cref="DynamicMetaObject"/> representing the result of the binding.</param>
/// <returns>true if operation was bound successfully; otherwise, false.</returns>
#if CLR2
[SecurityCritical, SecurityTreatAsSafe]
#else
[SecuritySafeCritical]
#endif
public static bool TryBindInvoke(InvokeBinder binder, DynamicMetaObject instance, DynamicMetaObject[] args, out DynamicMetaObject result) {
ContractUtils.RequiresNotNull(binder, "binder");
ContractUtils.RequiresNotNull(instance, "instance");
ContractUtils.RequiresNotNull(args, "args");
if (TryGetMetaObject(ref instance)) {
//
// Demand Full Trust to proceed with the binding.
//
new PermissionSet(PermissionState.Unrestricted).Demand();
result = instance.BindInvoke(binder, args);
return true;
} else {
result = null;
return false;
}
}
/// <summary>
/// Tries to perform binding of the dynamic invoke member operation.
/// </summary>
/// <param name="binder">An instance of the <see cref="InvokeMemberBinder"/> that represents the details of the dynamic operation.</param>
/// <param name="instance">The target of the dynamic operation. </param>
/// <param name="args">An array of <see cref="DynamicMetaObject"/> instances - arguments to the invoke member operation.</param>
/// <param name="result">The new <see cref="DynamicMetaObject"/> representing the result of the binding.</param>
/// <returns>true if operation was bound successfully; otherwise, false.</returns>
#if CLR2
[SecurityCritical, SecurityTreatAsSafe]
#else
[SecuritySafeCritical]
#endif
public static bool TryBindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject instance, DynamicMetaObject[] args, out DynamicMetaObject result) {
ContractUtils.RequiresNotNull(binder, "binder");
ContractUtils.RequiresNotNull(instance, "instance");
ContractUtils.RequiresNotNull(args, "args");
if (TryGetMetaObject(ref instance)) {
//
// Demand Full Trust to proceed with the binding.
//
new PermissionSet(PermissionState.Unrestricted).Demand();
result = instance.BindInvokeMember(binder, args);
return true;
} else {
result = null;
return false;
}
}
/// <summary>
/// Tries to perform binding of the dynamic get index operation.
/// </summary>
/// <param name="binder">An instance of the <see cref="GetIndexBinder"/> that represents the details of the dynamic operation.</param>
/// <param name="instance">The target of the dynamic operation. </param>
/// <param name="args">An array of <see cref="DynamicMetaObject"/> instances - arguments to the invoke member operation.</param>
/// <param name="result">The new <see cref="DynamicMetaObject"/> representing the result of the binding.</param>
/// <returns>true if operation was bound successfully; otherwise, false.</returns>
#if CLR2
[SecurityCritical, SecurityTreatAsSafe]
#else
[SecuritySafeCritical]
#endif
public static bool TryBindGetIndex(GetIndexBinder binder, DynamicMetaObject instance, DynamicMetaObject[] args, out DynamicMetaObject result) {
ContractUtils.RequiresNotNull(binder, "binder");
ContractUtils.RequiresNotNull(instance, "instance");
ContractUtils.RequiresNotNull(args, "args");
if (TryGetMetaObject(ref instance)) {
//
// Demand Full Trust to proceed with the binding.
//
new PermissionSet(PermissionState.Unrestricted).Demand();
result = instance.BindGetIndex(binder, args);
return true;
} else {
result = null;
return false;
}
}
/// <summary>
/// Tries to perform binding of the dynamic set index operation.
/// </summary>
/// <param name="binder">An instance of the <see cref="SetIndexBinder"/> that represents the details of the dynamic operation.</param>
/// <param name="instance">The target of the dynamic operation. </param>
/// <param name="args">An array of <see cref="DynamicMetaObject"/> instances - arguments to the invoke member operation.</param>
/// <param name="value">The <see cref="DynamicMetaObject"/> representing the value for the set index operation.</param>
/// <param name="result">The new <see cref="DynamicMetaObject"/> representing the result of the binding.</param>
/// <returns>true if operation was bound successfully; otherwise, false.</returns>
#if CLR2
[SecurityCritical, SecurityTreatAsSafe]
#else
[SecuritySafeCritical]
#endif
public static bool TryBindSetIndex(SetIndexBinder binder, DynamicMetaObject instance, DynamicMetaObject[] args, DynamicMetaObject value, out DynamicMetaObject result) {
ContractUtils.RequiresNotNull(binder, "binder");
ContractUtils.RequiresNotNull(instance, "instance");
ContractUtils.RequiresNotNull(args, "args");
ContractUtils.RequiresNotNull(value, "value");
if (TryGetMetaObject(ref instance)) {
//
// Demand Full Trust to proceed with the binding.
//
new PermissionSet(PermissionState.Unrestricted).Demand();
result = instance.BindSetIndex(binder, args, value);
return true;
} else {
result = null;
return false;
}
}
/// <summary>
/// Tries to perform binding of the dynamic Convert operation.
/// </summary>
/// <param name="binder">An instance of the <see cref="ConvertBinder"/> that represents the details of the dynamic operation.</param>
/// <param name="instance">The target of the dynamic operation.</param>
/// <param name="result">The new <see cref="DynamicMetaObject"/> representing the result of the binding.</param>
/// <returns>true if operation was bound successfully; otherwise, false.</returns>
#if CLR2
[SecurityCritical, SecurityTreatAsSafe]
#else
[SecuritySafeCritical]
#endif
public static bool TryConvert(ConvertBinder binder, DynamicMetaObject instance, out DynamicMetaObject result) {
ContractUtils.RequiresNotNull(binder, "binder");
ContractUtils.RequiresNotNull(instance, "instance");
if (IsComObject(instance.Value)) {
//
// Demand Full Trust to proceed with the binding.
//
new PermissionSet(PermissionState.Unrestricted).Demand();
// Converting a COM object to any interface is always considered possible - it will result in
// a QueryInterface at runtime
if (binder.Type.IsInterface) {
result = new DynamicMetaObject(
Expression.Convert(
instance.Expression,
binder.Type
),
BindingRestrictions.GetExpressionRestriction(
Expression.Call(
typeof(ComObject).GetMethod("IsComObject", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic),
Helpers.Convert(instance.Expression, typeof(object))
)
)
);
return true;
}
}
result = null;
return false;
}
/// <summary>
/// Gets the member names associated with the object.
/// This function can operate only with objects for which <see cref="IsComObject"/> returns true.
/// </summary>
/// <param name="value">The object for which member names are requested.</param>
/// <returns>The collection of member names.</returns>
#if CLR2
[SecurityCritical, SecurityTreatAsSafe]
#else
[SecuritySafeCritical]
#endif
public static IEnumerable<string> GetDynamicMemberNames(object value) {
ContractUtils.RequiresNotNull(value, "value");
ContractUtils.Requires(IsComObject(value), "value", Strings.ComObjectExpected);
//
// Demand Full Trust to proceed with the binding.
//
new PermissionSet(PermissionState.Unrestricted).Demand();
return ComObject.ObjectToComObject(value).GetMemberNames(false);
}
/// <summary>
/// Gets the member names of the data-like members associated with the object.
/// This function can operate only with objects for which <see cref="IsComObject"/> returns true.
/// </summary>
/// <param name="value">The object for which member names are requested.</param>
/// <returns>The collection of member names.</returns>
#if CLR2
[SecurityCritical, SecurityTreatAsSafe]
#else
[SecuritySafeCritical]
#endif
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal static IList<string> GetDynamicDataMemberNames(object value) {
ContractUtils.RequiresNotNull(value, "value");
ContractUtils.Requires(IsComObject(value), "value", Strings.ComObjectExpected);
//
// Demand Full Trust to proceed with the binding.
//
new PermissionSet(PermissionState.Unrestricted).Demand();
return ComObject.ObjectToComObject(value).GetMemberNames(true);
}
/// <summary>
/// Gets the data-like members and associated data for an object.
/// This function can operate only with objects for which <see cref="IsComObject"/> returns true.
/// </summary>
/// <param name="value">The object for which data members are requested.</param>
/// <param name="names">The enumeration of names of data members for which to retrieve values.</param>
/// <returns>The collection of pairs that represent data member's names and their data.</returns>
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
#if CLR2
[SecurityCritical, SecurityTreatAsSafe]
#else
[SecuritySafeCritical]
#endif
internal static IList<KeyValuePair<string, object>> GetDynamicDataMembers(object value, IEnumerable<string> names) {
ContractUtils.RequiresNotNull(value, "value");
ContractUtils.Requires(IsComObject(value), "value", Strings.ComObjectExpected);
//
// Demand Full Trust to proceed with the binding.
//
new PermissionSet(PermissionState.Unrestricted).Demand();
return ComObject.ObjectToComObject(value).GetMembers(names);
}
private static bool TryGetMetaObject(ref DynamicMetaObject instance) {
// If we're already a COM MO don't make a new one
// (we do this to prevent recursion if we call Fallback from COM)
if (instance is ComUnwrappedMetaObject) {
return false;
}
if (IsComObject(instance.Value)) {
instance = new ComMetaObject(instance.Expression, instance.Restrictions, instance.Value);
return true;
}
return false;
}
/// <summary>
/// Special binder that indicates special semantics for COM GetMember operation.
/// </summary>
internal class ComGetMemberBinder : GetMemberBinder {
private readonly GetMemberBinder _originalBinder;
internal bool _CanReturnCallables;
internal ComGetMemberBinder(GetMemberBinder originalBinder, bool CanReturnCallables) :
base(originalBinder.Name, originalBinder.IgnoreCase) {
_originalBinder = originalBinder;
_CanReturnCallables = CanReturnCallables;
}
public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion) {
return _originalBinder.FallbackGetMember(target, errorSuggestion);
}
public override int GetHashCode() {
return _originalBinder.GetHashCode() ^ (_CanReturnCallables ? 1 : 0);
}
public override bool Equals(object obj) {
ComGetMemberBinder other = obj as ComGetMemberBinder;
return other != null &&
_CanReturnCallables == other._CanReturnCallables &&
_originalBinder.Equals(other._originalBinder);
}
}
}
}
#endif

View File

@@ -0,0 +1,138 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Microsoft Public License. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Microsoft Public License, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Microsoft Public License.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System; using Microsoft;
#if !SILVERLIGHT
using System.Diagnostics;
#if CODEPLEX_40
using System.Dynamic;
using System.Dynamic.Utils;
using System.Linq.Expressions;
using System.Linq.Expressions.Compiler;
#else
using Microsoft.Scripting;
using Microsoft.Scripting.Utils;
using Microsoft.Linq.Expressions;
using Microsoft.Linq.Expressions.Compiler;
#endif
using System.Runtime.CompilerServices;
#if !CODEPLEX_40
using Microsoft.Runtime.CompilerServices;
#endif
using System.Runtime.InteropServices;
using System.Collections.Generic;
#if CODEPLEX_40
namespace System.Dynamic {
#else
namespace Microsoft.Scripting {
#endif
internal static class ComBinderHelpers {
internal static bool PreferPut(Type type, bool holdsNull) {
Debug.Assert(type != null);
if (type.IsValueType || type.IsArray) return true;
if (type == typeof(String) ||
type == typeof(DBNull) ||
holdsNull ||
type == typeof(System.Reflection.Missing) ||
type == typeof(CurrencyWrapper)) {
return true;
} else {
return false;
}
}
internal static bool IsByRef(DynamicMetaObject mo) {
ParameterExpression pe = mo.Expression as ParameterExpression;
return pe != null && pe.IsByRef;
}
internal static bool IsStrongBoxArg(DynamicMetaObject o) {
Type t = o.LimitType;
return t.IsGenericType && t.GetGenericTypeDefinition() == typeof(StrongBox<>);
}
// this helper prepares arguments for COM binding by transforming ByVal StongBox arguments
// into ByRef expressions that represent the argument's Value fields.
internal static bool[] ProcessArgumentsForCom(ref DynamicMetaObject[] args) {
Debug.Assert(args != null);
DynamicMetaObject[] newArgs = new DynamicMetaObject[args.Length];
bool[] isByRefArg = new bool[args.Length];
for (int i = 0; i < args.Length; i++) {
DynamicMetaObject curArgument = args[i];
// set new arg infos to their original values or set default ones
// we will do this fixup early so that we can assume we always have
// arginfos in COM binder.
if (IsByRef(curArgument)) {
newArgs[i] = curArgument;
isByRefArg[i] = true;
} else {
if (IsStrongBoxArg(curArgument)) {
var restrictions = curArgument.Restrictions.Merge(
GetTypeRestrictionForDynamicMetaObject(curArgument)
);
// we have restricted this argument to LimitType so we can convert and conversion will be trivial cast.
Expression boxedValueAccessor = Expression.Field(
Helpers.Convert(
curArgument.Expression,
curArgument.LimitType
),
curArgument.LimitType.GetField("Value")
);
IStrongBox value = curArgument.Value as IStrongBox;
object boxedValue = value != null ? value.Value : null;
newArgs[i] = new DynamicMetaObject(
boxedValueAccessor,
restrictions,
boxedValue
);
isByRefArg[i] = true;
} else {
newArgs[i] = curArgument;
isByRefArg[i] = false;
}
}
}
args = newArgs;
return isByRefArg;
}
internal static BindingRestrictions GetTypeRestrictionForDynamicMetaObject(DynamicMetaObject obj) {
if (obj.Value == null && obj.HasValue) {
//If the meta object holds a null value, create an instance restriction for checking null
return BindingRestrictions.GetInstanceRestriction(obj.Expression, null);
}
return BindingRestrictions.GetTypeRestriction(obj.Expression, obj.LimitType);
}
}
}
#endif

View File

@@ -0,0 +1,32 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Microsoft Public License. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Microsoft Public License, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Microsoft Public License.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System; using Microsoft;
#if !SILVERLIGHT // ComObject
#if CODEPLEX_40
namespace System.Dynamic {
#else
namespace Microsoft.Scripting {
#endif
internal static class ComDispIds {
internal const int DISPID_VALUE = 0;
internal const int DISPID_PROPERTYPUT = -3;
internal const int DISPID_NEWENUM = -4;
}
}
#endif

View File

@@ -0,0 +1,31 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Microsoft Public License. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Microsoft Public License, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Microsoft Public License.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System; using Microsoft;
#if !SILVERLIGHT // ComObject
#if CODEPLEX_40
namespace System.Dynamic {
#else
namespace Microsoft.Scripting {
#endif
internal class ComEventDesc {
internal Guid sourceIID;
internal int dispid;
};
}
#endif

View File

@@ -0,0 +1,349 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Microsoft Public License. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Microsoft Public License, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Microsoft Public License.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System; using Microsoft;
#if !SILVERLIGHT // ComObject
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security;
using ComTypes = System.Runtime.InteropServices.ComTypes;
#if CODEPLEX_40
namespace System.Dynamic {
#else
namespace Microsoft.Scripting {
#endif
/// <summary>
/// This class implements an event sink for a particular RCW.
/// Unlike the implementation of events in TlbImp'd assemblies,
/// we will create only one event sink per RCW (theoretically RCW might have
/// several ComEventSink evenk sinks - but all these implement different source intefaces).
/// Each ComEventSink contains a list of ComEventSinkMethod objects - which represent
/// a single method on the source interface an a multicast delegate to redirect
/// the calls. Notice that we are chaining multicast delegates so that same
/// ComEventSinkMedhod can invoke multiple event handlers).
///
/// ComEventSink implements an IDisposable pattern to Unadvise from the connection point.
/// Typically, when RCW is finalized the corresponding Dispose will be triggered by
/// ComEventSinksContainer finalizer. Notice that lifetime of ComEventSinksContainer
/// is bound to the lifetime of the RCW.
/// </summary>
internal sealed class ComEventSink : MarshalByRefObject, IReflect, IDisposable {
#region private fields
private Guid _sourceIid;
private ComTypes.IConnectionPoint _connectionPoint;
private int _adviseCookie;
private List<ComEventSinkMethod> _comEventSinkMethods;
private object _lockObject = new object(); // We cannot lock on ComEventSink since it causes a DoNotLockOnObjectsWithWeakIdentity warning
#endregion
#region private classes
/// <summary>
/// Contains a methods DISPID (in a string formatted of "[DISPID=N]"
/// and a chained list of delegates to invoke
/// </summary>
private class ComEventSinkMethod {
public string _name;
public Func<object[], object> _handlers;
}
#endregion
#region ctor
[SecurityCritical]
private ComEventSink(object rcw, Guid sourceIid) {
Initialize(rcw, sourceIid);
}
#endregion
[SecurityCritical]
private void Initialize(object rcw, Guid sourceIid) {
_sourceIid = sourceIid;
_adviseCookie = -1;
Debug.Assert(_connectionPoint == null, "re-initializing event sink w/o unadvising from connection point");
ComTypes.IConnectionPointContainer cpc = rcw as ComTypes.IConnectionPointContainer;
if (cpc == null)
throw Error.COMObjectDoesNotSupportEvents();
cpc.FindConnectionPoint(ref _sourceIid, out _connectionPoint);
if (_connectionPoint == null)
throw Error.COMObjectDoesNotSupportSourceInterface();
// Read the comments for ComEventSinkProxy about why we need it
ComEventSinkProxy proxy = new ComEventSinkProxy(this, _sourceIid);
_connectionPoint.Advise(proxy.GetTransparentProxy(), out _adviseCookie);
}
#region static methods
[SecurityCritical]
public static ComEventSink FromRuntimeCallableWrapper(object rcw, Guid sourceIid, bool createIfNotFound) {
List<ComEventSink> comEventSinks = ComEventSinksContainer.FromRuntimeCallableWrapper(rcw, createIfNotFound);
if (comEventSinks == null) {
return null;
}
ComEventSink comEventSink = null;
lock (comEventSinks) {
foreach (ComEventSink sink in comEventSinks) {
if (sink._sourceIid == sourceIid) {
comEventSink = sink;
break;
} else if (sink._sourceIid == Guid.Empty) {
// we found a ComEventSink object that
// was previously disposed. Now we will reuse it.
sink.Initialize(rcw, sourceIid);
comEventSink = sink;
}
}
if (comEventSink == null && createIfNotFound == true) {
comEventSink = new ComEventSink(rcw, sourceIid);
comEventSinks.Add(comEventSink);
}
}
return comEventSink;
}
#endregion
public void AddHandler(int dispid, object func) {
string name = String.Format(CultureInfo.InvariantCulture, "[DISPID={0}]", dispid);
lock (_lockObject) {
ComEventSinkMethod sinkMethod;
sinkMethod = FindSinkMethod(name);
if (sinkMethod == null) {
if (_comEventSinkMethods == null) {
_comEventSinkMethods = new List<ComEventSinkMethod>();
}
sinkMethod = new ComEventSinkMethod();
sinkMethod._name = name;
_comEventSinkMethods.Add(sinkMethod);
}
sinkMethod._handlers += new SplatCallSite(func).Invoke;
}
}
[SecurityCritical]
public void RemoveHandler(int dispid, object func) {
string name = String.Format(CultureInfo.InvariantCulture, "[DISPID={0}]", dispid);
lock (_lockObject) {
ComEventSinkMethod sinkEntry = FindSinkMethod(name);
if (sinkEntry == null){
return;
}
// Remove the delegate from multicast delegate chain.
// We will need to find the delegate that corresponds
// to the func handler we want to remove. This will be
// easy since we Target property of the delegate object
// is a ComEventCallContext object.
Delegate[] delegates = sinkEntry._handlers.GetInvocationList();
foreach (Delegate d in delegates) {
SplatCallSite callContext = d.Target as SplatCallSite;
if (callContext != null && callContext._callable.Equals(func)) {
sinkEntry._handlers -= d as Func<object[], object>;
break;
}
}
// If the delegates chain is empty - we can remove
// corresponding ComEvenSinkEntry
if (sinkEntry._handlers == null)
_comEventSinkMethods.Remove(sinkEntry);
// We can Unadvise from the ConnectionPoint if no more sink entries
// are registered for this interface
//(calling Dispose will call IConnectionPoint.Unadvise).
if (_comEventSinkMethods.Count == 0) {
// notice that we do not remove
// ComEventSinkEntry from the list, we will re-use this data structure
// if a new handler needs to be attached.
Dispose();
}
}
}
public object ExecuteHandler(string name, object[] args) {
ComEventSinkMethod site;
site = FindSinkMethod(name);
if (site != null && site._handlers != null) {
return site._handlers(args);
}
return null;
}
#region IReflect
#region Unimplemented members
public FieldInfo GetField(string name, BindingFlags bindingAttr) {
return null;
}
public FieldInfo[] GetFields(BindingFlags bindingAttr) {
return new FieldInfo[0];
}
public MemberInfo[] GetMember(string name, BindingFlags bindingAttr) {
return new MemberInfo[0];
}
public MemberInfo[] GetMembers(BindingFlags bindingAttr) {
return new MemberInfo[0];
}
public MethodInfo GetMethod(string name, BindingFlags bindingAttr) {
return null;
}
public MethodInfo GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers) {
return null;
}
public MethodInfo[] GetMethods(BindingFlags bindingAttr) {
return new MethodInfo[0];
}
public PropertyInfo GetProperty(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) {
return null;
}
public PropertyInfo GetProperty(string name, BindingFlags bindingAttr) {
return null;
}
public PropertyInfo[] GetProperties(BindingFlags bindingAttr) {
return new PropertyInfo[0];
}
#endregion
public Type UnderlyingSystemType {
get {
return typeof(object);
}
}
public object InvokeMember(
string name,
BindingFlags invokeAttr,
Binder binder,
object target,
object[] args,
ParameterModifier[] modifiers,
CultureInfo culture,
string[] namedParameters) {
return ExecuteHandler(name, args);
}
#endregion
#region IDisposable
#if CLR2
[SecurityCritical, SecurityTreatAsSafe]
#else
[SecuritySafeCritical]
#endif
public void Dispose() {
DisposeAll();
GC.SuppressFinalize(this);
}
#endregion
#if CLR2
[SecurityCritical, SecurityTreatAsSafe]
#else
[SecuritySafeCritical]
#endif
~ComEventSink() {
DisposeAll();
}
[SecurityCritical]
private void DisposeAll() {
if (_connectionPoint == null) {
return;
}
if (_adviseCookie == -1) {
return;
}
try {
_connectionPoint.Unadvise(_adviseCookie);
// _connectionPoint has entered the CLR in the constructor
// for this object and hence its ref counter has been increased
// by us. We have not exposed it to other components and
// hence it is safe to call RCO on it w/o worrying about
// killing the RCW for other objects that link to it.
Marshal.ReleaseComObject(_connectionPoint);
} catch (Exception ex) {
// if something has gone wrong, and the object is no longer attached to the CLR,
// the Unadvise is going to throw. In this case, since we're going away anyway,
// we'll ignore the failure and quietly go on our merry way.
COMException exCOM = ex as COMException;
if (exCOM != null && exCOM.ErrorCode == ComHresults.CONNECT_E_NOCONNECTION) {
Debug.Assert(false, "IConnectionPoint::Unadvise returned CONNECT_E_NOCONNECTION.");
throw;
}
} finally {
_connectionPoint = null;
_adviseCookie = -1;
_sourceIid = Guid.Empty;
}
}
private ComEventSinkMethod FindSinkMethod(string name) {
if (_comEventSinkMethods == null)
return null;
ComEventSinkMethod site;
site = _comEventSinkMethods.Find(element => element._name == name);
return site;
}
}
}
#endif

View File

@@ -0,0 +1,148 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Microsoft Public License. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Microsoft Public License, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Microsoft Public License.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System; using Microsoft;
#if !SILVERLIGHT // ComObject
using System.Globalization;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
using System.Security;
using System.Security.Permissions;
#if CODEPLEX_40
namespace System.Dynamic {
#else
namespace Microsoft.Scripting {
#endif
/// <summary>
/// ComEventSinkProxy class is responsible for handling QIs for sourceIid
/// on instances of ComEventSink.
///
/// Background: When a COM even sink advises to a connection point it is
/// supposed to hand over the dispinterface. Now, some hosts will trust
/// the COM client to pass the correct pointer, but some will not.
/// E.g. Excel's implementation of Connection Points will not cause a
/// QI on the pointer that has been passed, however Word will QI the
/// pointer to return the required interface.
///
/// ComEventSink does not, strongly speaking, implements the interface
/// that it claims to implement - it is just "faking" it by using IReflect.
/// Thus, Word's QIs on the pointer passed to ICP::Advise would fail. To
/// prevent this we take advangate of RealProxy's ability of
/// "dressing up" like other classes and hence successfully respond to QIs
/// for interfaces that it does not really support( it is OK to say
/// "I implement this interface" for event sinks only since the common
/// practice is to use IDistpach.Invoke when calling into event sinks).
/// </summary>
[SecurityCritical]
internal sealed class ComEventSinkProxy : RealProxy {
private Guid _sinkIid;
private ComEventSink _sink;
private static readonly MethodInfo _methodInfoInvokeMember = typeof(ComEventSink).GetMethod("InvokeMember", BindingFlags.Instance | BindingFlags.Public);
#region ctors
[SecurityCritical]
private ComEventSinkProxy() {
}
[SecurityCritical]
public ComEventSinkProxy(ComEventSink sink, Guid sinkIid)
: base(typeof(ComEventSink)) {
_sink = sink;
_sinkIid = sinkIid;
}
#endregion
#region Base Class Overrides
#if CLR2
// to match the base method
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
#else
[SecurityCritical]
#endif
public override IntPtr SupportsInterface(ref Guid iid) {
// if the iid is the sink iid, we ask the base class for an rcw to IDispatch
if (iid == _sinkIid) {
IntPtr retVal = IntPtr.Zero;
retVal = Marshal.GetIDispatchForObject(_sink);
return retVal;
}
return base.SupportsInterface(ref iid);
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
#if CLR2
// to match the base method
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
#else
[SecurityCritical]
#endif
public override IMessage Invoke(IMessage msg) {
ContractUtils.RequiresNotNull(msg, "msg");
//Only know how to handle method calls (property and fields accessors count as methods)
IMethodCallMessage methodCallMessage = msg as IMethodCallMessage;
if (methodCallMessage == null)
throw new NotSupportedException();
// ComEventSink.InvokeMember is handled specially.
// The reason we need to do that is due to how namedParameters arg (7th element in the IMethodCallMessage.Args array)
// is marshalled when called through RealProxy.Invoke.
// In RealProxy.Invoke namedParameters is typed as object[], while InvokeMember expects it to be string[].
// If we simply let this call go through (with RemotingServices.ExecuteMessage)
// we get an InvalidCastException when Remoting tries to pass namedParameters (of type object[])
// to InvokeMember (which expects namedParameters to be string[]).
// Since we don't use namedParameters in ComEventSink.InvokeMember - we simply ignore it here
// and pass-in null.
MethodInfo methodInfo = (MethodInfo)methodCallMessage.MethodBase;
if (methodInfo == _methodInfoInvokeMember) {
object retVal = null;
try {
// InvokeMember(string name, BindingFlags bindingFlags, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters)
retVal = ((IReflect)_sink).InvokeMember(
/*name*/ methodCallMessage.Args[0] as string,
/*bindingFlags*/ (BindingFlags)methodCallMessage.Args[1],
/*binder*/ methodCallMessage.Args[2] as Binder,
/*target*/ null,
/*args*/ methodCallMessage.Args[4] as object[],
/*modifiers*/ methodCallMessage.Args[5] as ParameterModifier[],
/*culture*/ methodCallMessage.Args[6] as CultureInfo,
/*namedParameters*/ null);
} catch (Exception ex) {
return new ReturnMessage(ex.InnerException, methodCallMessage);
}
return new ReturnMessage(retVal, methodCallMessage.Args, methodCallMessage.ArgCount, null, methodCallMessage);
}
return RemotingServices.ExecuteMessage(_sink, methodCallMessage);
}
#endregion
}
}
#endif

View File

@@ -0,0 +1,98 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Microsoft Public License. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Microsoft Public License, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Microsoft Public License.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System; using Microsoft;
#if !SILVERLIGHT // ComObject
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Security;
#if CODEPLEX_40
namespace System.Dynamic {
#else
namespace Microsoft.Scripting {
#endif
/// <summary>
/// ComEventSinksContainer is just a regular list with a finalizer.
/// This list is usually attached as a custom data for RCW object and
/// is finalized whenever RCW is finalized.
/// </summary>
internal class ComEventSinksContainer : List<ComEventSink>, IDisposable {
private ComEventSinksContainer() {
}
private static readonly object _ComObjectEventSinksKey = new object();
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists")]
[SecurityCritical]
public static ComEventSinksContainer FromRuntimeCallableWrapper(object rcw, bool createIfNotFound) {
// !!! Marshal.Get/SetComObjectData has a LinkDemand for UnmanagedCode which will turn into
// a full demand. We need to avoid this by making this method SecurityCritical
object data = Marshal.GetComObjectData(rcw, _ComObjectEventSinksKey);
if (data != null || createIfNotFound == false) {
return (ComEventSinksContainer)data;
}
lock (_ComObjectEventSinksKey) {
data = Marshal.GetComObjectData(rcw, _ComObjectEventSinksKey);
if (data != null) {
return (ComEventSinksContainer)data;
}
ComEventSinksContainer comEventSinks = new ComEventSinksContainer();
if (!Marshal.SetComObjectData(rcw, _ComObjectEventSinksKey, comEventSinks)) {
throw Error.SetComObjectDataFailed();
}
return comEventSinks;
}
}
#region IDisposable Members
#if CLR2
[SecurityCritical, SecurityTreatAsSafe]
#else
[SecuritySafeCritical]
#endif
public void Dispose() {
DisposeAll();
GC.SuppressFinalize(this);
}
#endregion
[SecurityCritical]
private void DisposeAll() {
foreach (ComEventSink sink in this) {
sink.Dispose();
}
}
#if CLR2
[SecurityCritical, SecurityTreatAsSafe]
#else
[SecuritySafeCritical]
#endif
~ComEventSinksContainer() {
DisposeAll();
}
}
}
#endif

View File

@@ -0,0 +1,92 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Microsoft Public License. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Microsoft Public License, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Microsoft Public License.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System; using Microsoft;
#if !SILVERLIGHT
#if CODEPLEX_40
using System.Linq.Expressions;
using System.Dynamic;
using System.Dynamic.Utils;
#else
using Microsoft.Linq.Expressions;
using Microsoft.Scripting;
using Microsoft.Scripting.Utils;
#endif
using System.Diagnostics;
#if CODEPLEX_40
namespace System.Dynamic {
#else
namespace Microsoft.Scripting {
#endif
//
// ComFallbackMetaObject just delegates everything to the binder.
//
// Note that before performing FallBack on a ComObject we need to unwrap it so that
// binder would act upon the actual object (typically Rcw)
//
// Also: we don't need to implement these for any operations other than those
// supported by ComBinder
internal class ComFallbackMetaObject : DynamicMetaObject {
internal ComFallbackMetaObject(Expression expression, BindingRestrictions restrictions, object arg)
: base(expression, restrictions, arg) {
}
public override DynamicMetaObject BindGetIndex(GetIndexBinder binder, DynamicMetaObject[] indexes) {
ContractUtils.RequiresNotNull(binder, "binder");
return binder.FallbackGetIndex(UnwrapSelf(), indexes);
}
public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value) {
ContractUtils.RequiresNotNull(binder, "binder");
return binder.FallbackSetIndex(UnwrapSelf(), indexes, value);
}
public override DynamicMetaObject BindGetMember(GetMemberBinder binder) {
ContractUtils.RequiresNotNull(binder, "binder");
return binder.FallbackGetMember(UnwrapSelf());
}
public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args) {
ContractUtils.RequiresNotNull(binder, "binder");
return binder.FallbackInvokeMember(UnwrapSelf(), args);
}
public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value) {
ContractUtils.RequiresNotNull(binder, "binder");
return binder.FallbackSetMember(UnwrapSelf(), value);
}
protected virtual ComUnwrappedMetaObject UnwrapSelf() {
return new ComUnwrappedMetaObject(
ComObject.RcwFromComObject(Expression),
Restrictions.Merge(ComBinderHelpers.GetTypeRestrictionForDynamicMetaObject(this)),
((ComObject)Value).RuntimeCallableWrapper
);
}
}
// This type exists as a signal type, so ComBinder knows not to try to bind
// again when we're trying to fall back
internal sealed class ComUnwrappedMetaObject : DynamicMetaObject {
internal ComUnwrappedMetaObject(Expression expression, BindingRestrictions restrictions, object value)
: base(expression, restrictions, value) {
}
}
}
#endif

View File

@@ -0,0 +1,58 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Microsoft Public License. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Microsoft Public License, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Microsoft Public License.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System; using Microsoft;
#if !SILVERLIGHT // ComObject
#if CODEPLEX_40
namespace System.Dynamic {
#else
namespace Microsoft.Scripting {
#endif
internal static class ComHresults {
internal const int S_OK = 0;
internal const int CONNECT_E_NOCONNECTION = unchecked((int)0x80040200);
internal const int DISP_E_UNKNOWNINTERFACE = unchecked((int)0x80020001);
internal const int DISP_E_MEMBERNOTFOUND = unchecked((int)0x80020003);
internal const int DISP_E_PARAMNOTFOUND = unchecked((int)0x80020004);
internal const int DISP_E_TYPEMISMATCH = unchecked((int)0x80020005);
internal const int DISP_E_UNKNOWNNAME = unchecked((int)0x80020006); // GetIDsOfName
internal const int DISP_E_NONAMEDARGS = unchecked((int)0x80020007);
internal const int DISP_E_BADVARTYPE = unchecked((int)0x80020008);
internal const int DISP_E_EXCEPTION = unchecked((int)0x80020009);
internal const int DISP_E_OVERFLOW = unchecked((int)0x8002000A);
internal const int DISP_E_BADINDEX = unchecked((int)0x8002000B); // GetTypeInfo
internal const int DISP_E_UNKNOWNLCID = unchecked((int)0x8002000C);
internal const int DISP_E_ARRAYISLOCKED = unchecked((int)0x8002000D); // VariantClear
internal const int DISP_E_BADPARAMCOUNT = unchecked((int)0x8002000E);
internal const int DISP_E_PARAMNOTOPTIONAL = unchecked((int)0x8002000F);
internal const int E_NOINTERFACE = unchecked((int)0x80004002);
internal const int E_FAIL = unchecked((int)0x80004005);
internal const int TYPE_E_LIBNOTREGISTERED = unchecked((int)0x8002801D);
internal static bool IsSuccess(int hresult) {
return hresult >= 0;
}
}
}
#endif

View File

@@ -0,0 +1,98 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Microsoft Public License. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Microsoft Public License, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Microsoft Public License.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System; using Microsoft;
#if !SILVERLIGHT // ComObject
using System.Runtime.InteropServices;
using ComTypes = System.Runtime.InteropServices.ComTypes;
#if CODEPLEX_40
namespace System.Dynamic {
#else
namespace Microsoft.Scripting {
#endif
[
ComImport,
InterfaceType(ComInterfaceType.InterfaceIsIDispatch),
Guid("00020400-0000-0000-C000-000000000046")
]
internal interface IDispatchForReflection {
}
[
ComImport,
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
Guid("00020400-0000-0000-C000-000000000046"),
]
internal interface IDispatch {
[PreserveSig]
int TryGetTypeInfoCount(out uint pctinfo);
[PreserveSig]
int TryGetTypeInfo(uint iTInfo, int lcid, out IntPtr info);
[PreserveSig]
int TryGetIDsOfNames(
ref Guid iid,
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 2)]
string[] names,
uint cNames,
int lcid,
[Out]
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I4, SizeParamIndex = 2)]
int[] rgDispId);
[PreserveSig]
int TryInvoke(
int dispIdMember,
ref Guid riid,
int lcid,
ComTypes.INVOKEKIND wFlags,
ref ComTypes.DISPPARAMS pDispParams,
out object VarResult,
out ComTypes.EXCEPINFO pExcepInfo,
out uint puArgErr);
}
/// <summary>
/// Layout of the IDispatch vtable
/// </summary>
internal enum IDispatchMethodIndices {
IUnknown_QueryInterface,
IUnknown_AddRef,
IUnknown_Release,
IDispatch_GetTypeInfoCount ,
IDispatch_GetTypeInfo,
IDispatch_GetIDsOfNames,
IDispatch_Invoke
}
[
ComImport,
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
Guid("B196B283-BAB4-101A-B69C-00AA00341D07")
]
internal interface IProvideClassInfo {
void GetClassInfo(out IntPtr info);
}
}
#endif

View File

@@ -0,0 +1,107 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Microsoft Public License. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Microsoft Public License, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Microsoft Public License.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System; using Microsoft;
#if !SILVERLIGHT
using System.Collections.ObjectModel;
using System.Diagnostics;
#if CODEPLEX_40
using System.Linq.Expressions;
#else
using Microsoft.Linq.Expressions;
#endif
using System.Runtime.CompilerServices;
#if !CODEPLEX_40
using Microsoft.Runtime.CompilerServices;
#endif
#if CODEPLEX_40
namespace System.Dynamic {
#else
namespace Microsoft.Scripting {
#endif
/// <summary>
/// Invokes the object. If it falls back, just produce an error.
/// </summary>
internal sealed class ComInvokeAction : InvokeBinder {
internal ComInvokeAction(CallInfo callInfo)
: base(callInfo) {
}
public override int GetHashCode() {
return base.GetHashCode();
}
public override bool Equals(object obj) {
return base.Equals(obj as ComInvokeAction);
}
public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) {
return errorSuggestion ?? new DynamicMetaObject(
Expression.Throw(
Expression.New(
typeof(NotSupportedException).GetConstructor(new[] { typeof(string) }),
Expression.Constant(Strings.CannotCall)
)
),
target.Restrictions.Merge(BindingRestrictions.Combine(args))
);
}
}
/// <summary>
/// Splats the arguments to another nested dynamic site, which does the
/// real invocation of the IDynamicMetaObjectProvider.
/// </summary>
internal sealed class SplatInvokeBinder : CallSiteBinder {
internal readonly static SplatInvokeBinder Instance = new SplatInvokeBinder();
// Just splat the args and dispatch through a nested site
public override Expression Bind(object[] args, ReadOnlyCollection<ParameterExpression> parameters, LabelTarget returnLabel) {
Debug.Assert(args.Length == 2);
int count = ((object[])args[1]).Length;
ParameterExpression array = parameters[1];
var nestedArgs = new ReadOnlyCollectionBuilder<Expression>(count + 1);
var delegateArgs = new Type[count + 3]; // args + target + returnType + CallSite
nestedArgs.Add(parameters[0]);
delegateArgs[0] = typeof(CallSite);
delegateArgs[1] = typeof(object);
for (int i = 0; i < count; i++) {
nestedArgs.Add(Expression.ArrayAccess(array, Expression.Constant(i)));
delegateArgs[i + 2] = typeof(object).MakeByRefType();
}
delegateArgs[delegateArgs.Length - 1] = typeof(object);
return Expression.IfThen(
Expression.Equal(Expression.ArrayLength(array), Expression.Constant(count)),
Expression.Return(
returnLabel,
Expression.MakeDynamic(
Expression.GetDelegateType(delegateArgs),
new ComInvokeAction(new CallInfo(count)),
nestedArgs
)
)
);
}
}
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,87 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Microsoft Public License. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Microsoft Public License, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Microsoft Public License.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System; using Microsoft;
#if !SILVERLIGHT
#if CODEPLEX_40
using System.Linq.Expressions;
using System.Dynamic;
using System.Dynamic.Utils;
#else
using Microsoft.Linq.Expressions;
using Microsoft.Scripting;
using Microsoft.Scripting.Utils;
#endif
using System.Collections.Generic;
#if CODEPLEX_40
namespace System.Dynamic {
#else
namespace Microsoft.Scripting {
#endif
// Note: we only need to support the operations used by ComBinder
internal class ComMetaObject : DynamicMetaObject {
internal ComMetaObject(Expression expression, BindingRestrictions restrictions, object arg)
: base(expression, restrictions, arg) {
}
public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args) {
ContractUtils.RequiresNotNull(binder, "binder");
return binder.Defer(args.AddFirst(WrapSelf()));
}
public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args) {
ContractUtils.RequiresNotNull(binder, "binder");
return binder.Defer(args.AddFirst(WrapSelf()));
}
public override DynamicMetaObject BindGetMember(GetMemberBinder binder) {
ContractUtils.RequiresNotNull(binder, "binder");
return binder.Defer(WrapSelf());
}
public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value) {
ContractUtils.RequiresNotNull(binder, "binder");
return binder.Defer(WrapSelf(), value);
}
public override DynamicMetaObject BindGetIndex(GetIndexBinder binder, DynamicMetaObject[] indexes) {
ContractUtils.RequiresNotNull(binder, "binder");
return binder.Defer(WrapSelf(), indexes);
}
public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value) {
ContractUtils.RequiresNotNull(binder, "binder");
return binder.Defer(WrapSelf(), indexes.AddLast(value));
}
private DynamicMetaObject WrapSelf() {
return new DynamicMetaObject(
ComObject.RcwToComObject(Expression),
BindingRestrictions.GetExpressionRestriction(
Expression.Call(
typeof(ComObject).GetMethod("IsComObject", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic),
Helpers.Convert(Expression, typeof(object))
)
)
);
}
}
}
#endif

Some files were not shown because too many files have changed in this diff Show More