PageRenderTime 47ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/IronPython_Main/Runtime/Microsoft.Dynamic/ComInterop/ComObject.cs

#
C# | 137 lines | 82 code | 23 blank | 32 comment | 11 complexity | 997e56684acc1e7122818722c704cdcf MD5 | raw file
Possible License(s): GPL-2.0, MPL-2.0-no-copyleft-exception, CPL-1.0, CC-BY-SA-3.0, BSD-3-Clause, ISC, AGPL-3.0, LGPL-2.1, Apache-2.0
  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  5. * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
  6. * copy of the license can be found in the License.html file at the root of this distribution. If
  7. * you cannot locate the Apache License, Version 2.0, please send an email to
  8. * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
  9. * by the terms of the Apache License, Version 2.0.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. *
  14. * ***************************************************************************/
  15. #if !SILVERLIGHT // ComObject
  16. #if !CLR2
  17. using System.Linq.Expressions;
  18. #else
  19. using Microsoft.Scripting.Ast;
  20. #endif
  21. using System;
  22. using System.Collections.Generic;
  23. using System.Diagnostics;
  24. using System.Reflection;
  25. using System.Runtime.InteropServices;
  26. using System.Security;
  27. using System.Security.Permissions;
  28. using System.Dynamic;
  29. namespace Microsoft.Scripting.ComInterop {
  30. /// <summary>
  31. /// This is a helper class for runtime-callable-wrappers of COM instances. We create one instance of this type
  32. /// for every generic RCW instance.
  33. /// </summary>
  34. internal class ComObject : IDynamicMetaObjectProvider {
  35. /// <summary>
  36. /// The runtime-callable wrapper
  37. /// </summary>
  38. private readonly object _rcw;
  39. internal ComObject(object rcw) {
  40. Debug.Assert(ComObject.IsComObject(rcw));
  41. _rcw = rcw;
  42. }
  43. internal object RuntimeCallableWrapper {
  44. get {
  45. return _rcw;
  46. }
  47. }
  48. private readonly static object _ComObjectInfoKey = new object();
  49. /// <summary>
  50. /// This is the factory method to get the ComObject corresponding to an RCW
  51. /// </summary>
  52. /// <returns></returns>
  53. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")]
  54. public static ComObject ObjectToComObject(object rcw) {
  55. Debug.Assert(ComObject.IsComObject(rcw));
  56. // Marshal.Get/SetComObjectData has a LinkDemand for UnmanagedCode which will turn into
  57. // a full demand. We could avoid this by making this method SecurityCritical
  58. object data = Marshal.GetComObjectData(rcw, _ComObjectInfoKey);
  59. if (data != null) {
  60. return (ComObject)data;
  61. }
  62. lock (_ComObjectInfoKey) {
  63. data = Marshal.GetComObjectData(rcw, _ComObjectInfoKey);
  64. if (data != null) {
  65. return (ComObject)data;
  66. }
  67. ComObject comObjectInfo = CreateComObject(rcw);
  68. if (!Marshal.SetComObjectData(rcw, _ComObjectInfoKey, comObjectInfo)) {
  69. throw Error.SetComObjectDataFailed();
  70. }
  71. return comObjectInfo;
  72. }
  73. }
  74. // Expression that unwraps ComObject
  75. internal static MemberExpression RcwFromComObject(Expression comObject) {
  76. Debug.Assert(comObject != null && typeof(ComObject).IsAssignableFrom(comObject.Type), "must be ComObject");
  77. return Expression.Property(
  78. Helpers.Convert(comObject, typeof(ComObject)),
  79. typeof(ComObject).GetProperty("RuntimeCallableWrapper", BindingFlags.NonPublic | BindingFlags.Instance)
  80. );
  81. }
  82. // Expression that finds or creates a ComObject that corresponds to given Rcw
  83. internal static MethodCallExpression RcwToComObject(Expression rcw) {
  84. return Expression.Call(
  85. typeof(ComObject).GetMethod("ObjectToComObject"),
  86. Helpers.Convert(rcw, typeof(object))
  87. );
  88. }
  89. private static ComObject CreateComObject(object rcw) {
  90. IDispatch dispatchObject = rcw as IDispatch;
  91. if (dispatchObject != null) {
  92. // We can do method invocations on IDispatch objects
  93. return new IDispatchComObject(dispatchObject);
  94. }
  95. // There is not much we can do in this case
  96. return new ComObject(rcw);
  97. }
  98. internal virtual IList<string> GetMemberNames(bool dataOnly) {
  99. return new string[0];
  100. }
  101. internal virtual IList<KeyValuePair<string, object>> GetMembers(IEnumerable<string> names) {
  102. return new KeyValuePair<string, object>[0];
  103. }
  104. DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter) {
  105. return new ComFallbackMetaObject(parameter, BindingRestrictions.Empty, this);
  106. }
  107. private static readonly Type ComObjectType = typeof(object).Assembly.GetType("System.__ComObject");
  108. internal static bool IsComObject(object obj) {
  109. // we can't use System.Runtime.InteropServices.Marshal.IsComObject(obj) since it doesn't work in partial trust
  110. return obj != null && ComObjectType.IsAssignableFrom(obj.GetType());
  111. }
  112. }
  113. }
  114. #endif