PageRenderTime 43ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/Microsoft.Scripting/ComInterop/ComTypeLibDesc.cs

https://bitbucket.org/stefanrusek/xronos
C# | 225 lines | 145 code | 42 blank | 38 comment | 20 complexity | 58d1aa78e4367165129733e1292bb68d MD5 | raw file
  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  5. * This source code is subject to terms and conditions of the Microsoft Public License. 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 Microsoft Public License, 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 Microsoft Public License.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. *
  14. * ***************************************************************************/
  15. #if !SILVERLIGHT // ComObject
  16. #if CODEPLEX_40
  17. using System;
  18. #else
  19. using System; using Microsoft;
  20. #endif
  21. using System.Collections.Generic;
  22. #if CODEPLEX_40
  23. using System.Linq.Expressions;
  24. #else
  25. using Microsoft.Linq.Expressions;
  26. #endif
  27. using System.Runtime.InteropServices;
  28. #if CODEPLEX_40
  29. using System.Dynamic;
  30. #else
  31. using Microsoft.Scripting;
  32. #endif
  33. using System.Globalization;
  34. using ComTypes = System.Runtime.InteropServices.ComTypes;
  35. namespace Microsoft.Scripting.ComInterop {
  36. public sealed class ComTypeLibDesc : IDynamicMetaObjectProvider {
  37. // typically typelibs contain very small number of coclasses
  38. // so we will just use the linked list as it performs better
  39. // on small number of entities
  40. LinkedList<ComTypeClassDesc> _classes;
  41. Dictionary<string, ComTypeEnumDesc> _enums;
  42. string _typeLibName;
  43. ComTypes.TYPELIBATTR _typeLibAttributes;
  44. private static Dictionary<Guid, ComTypeLibDesc> _CachedTypeLibDesc = new Dictionary<Guid, ComTypeLibDesc>();
  45. private ComTypeLibDesc() {
  46. _enums = new Dictionary<string, ComTypeEnumDesc>();
  47. _classes = new LinkedList<ComTypeClassDesc>();
  48. }
  49. public override string ToString() {
  50. return String.Format(CultureInfo.CurrentCulture, "<type library {0}>", _typeLibName);
  51. }
  52. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
  53. public string Documentation {
  54. get { return String.Empty; }
  55. }
  56. #region IDynamicMetaObjectProvider Members
  57. DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter) {
  58. return new TypeLibMetaObject(parameter, this);
  59. }
  60. #endregion
  61. /// <summary>
  62. /// Reads the latest registered type library for the corresponding GUID,
  63. /// reads definitions of CoClass'es and Enum's from this library
  64. /// and creates a IDynamicMetaObjectProvider that allows to instantiate coclasses
  65. /// and get actual values for the enums.
  66. /// </summary>
  67. /// <param name="typeLibGuid">Type Library Guid</param>
  68. /// <returns>ComTypeLibDesc object</returns>
  69. [System.Runtime.Versioning.ResourceExposure(System.Runtime.Versioning.ResourceScope.Machine)]
  70. [System.Runtime.Versioning.ResourceConsumption(System.Runtime.Versioning.ResourceScope.Machine, System.Runtime.Versioning.ResourceScope.Machine)]
  71. public static ComTypeLibInfo CreateFromGuid(Guid typeLibGuid) {
  72. // passing majorVersion = -1, minorVersion = -1 will always
  73. // load the latest typelib
  74. ComTypes.ITypeLib typeLib = UnsafeNativeMethods.LoadRegTypeLib(ref typeLibGuid, -1, -1, 0);
  75. return new ComTypeLibInfo(GetFromTypeLib(typeLib));
  76. }
  77. /// <summary>
  78. /// Gets an ITypeLib object from OLE Automation compatible RCW ,
  79. /// reads definitions of CoClass'es and Enum's from this library
  80. /// and creates a IDynamicMetaObjectProvider that allows to instantiate coclasses
  81. /// and get actual values for the enums.
  82. /// </summary>
  83. /// <param name="rcw">OLE automation compatible RCW</param>
  84. /// <returns>ComTypeLibDesc object</returns>
  85. public static ComTypeLibInfo CreateFromObject(object rcw) {
  86. if (Marshal.IsComObject(rcw) == false) {
  87. throw new ArgumentException("COM object is expected.");
  88. }
  89. ComTypes.ITypeInfo typeInfo = ComRuntimeHelpers.GetITypeInfoFromIDispatch(rcw as IDispatch, true);
  90. ComTypes.ITypeLib typeLib;
  91. int typeInfoIndex;
  92. typeInfo.GetContainingTypeLib(out typeLib, out typeInfoIndex);
  93. return new ComTypeLibInfo(GetFromTypeLib(typeLib));
  94. }
  95. internal static ComTypeLibDesc GetFromTypeLib(ComTypes.ITypeLib typeLib) {
  96. // check whether we have already loaded this type library
  97. ComTypes.TYPELIBATTR typeLibAttr = ComRuntimeHelpers.GetTypeAttrForTypeLib(typeLib);
  98. ComTypeLibDesc typeLibDesc;
  99. lock (_CachedTypeLibDesc) {
  100. if (_CachedTypeLibDesc.TryGetValue(typeLibAttr.guid, out typeLibDesc)) {
  101. return typeLibDesc;
  102. }
  103. }
  104. typeLibDesc = new ComTypeLibDesc();
  105. typeLibDesc._typeLibName = ComRuntimeHelpers.GetNameOfLib(typeLib);
  106. typeLibDesc._typeLibAttributes = typeLibAttr;
  107. int countTypes = typeLib.GetTypeInfoCount();
  108. for (int i = 0; i < countTypes; i++) {
  109. ComTypes.TYPEKIND typeKind;
  110. typeLib.GetTypeInfoType(i, out typeKind);
  111. ComTypes.ITypeInfo typeInfo;
  112. if (typeKind == ComTypes.TYPEKIND.TKIND_COCLASS) {
  113. typeLib.GetTypeInfo(i, out typeInfo);
  114. ComTypeClassDesc classDesc = new ComTypeClassDesc(typeInfo, typeLibDesc);
  115. typeLibDesc._classes.AddLast(classDesc);
  116. } else if (typeKind == ComTypes.TYPEKIND.TKIND_ENUM) {
  117. typeLib.GetTypeInfo(i, out typeInfo);
  118. ComTypeEnumDesc enumDesc = new ComTypeEnumDesc(typeInfo, typeLibDesc);
  119. typeLibDesc._enums.Add(enumDesc.TypeName, enumDesc);
  120. }
  121. }
  122. // cached the typelib using the guid as the dictionary key
  123. lock (_CachedTypeLibDesc) {
  124. _CachedTypeLibDesc.Add(typeLibAttr.guid, typeLibDesc);
  125. }
  126. return typeLibDesc;
  127. }
  128. public object GetTypeLibObjectDesc(string member) {
  129. foreach (ComTypeClassDesc coclass in _classes) {
  130. if (member == coclass.TypeName) {
  131. return coclass;
  132. }
  133. }
  134. ComTypeEnumDesc enumDesc;
  135. if (_enums != null && _enums.TryGetValue(member, out enumDesc) == true)
  136. return enumDesc;
  137. return null;
  138. }
  139. // TODO: internal
  140. public string[] GetMemberNames() {
  141. string[] retval = new string[_enums.Count + _classes.Count];
  142. int i = 0;
  143. foreach (ComTypeClassDesc coclass in _classes) {
  144. retval[i++] = coclass.TypeName;
  145. }
  146. foreach (KeyValuePair<string, ComTypeEnumDesc> enumDesc in _enums) {
  147. retval[i++] = enumDesc.Key;
  148. }
  149. return retval;
  150. }
  151. internal bool HasMember(string member) {
  152. foreach (ComTypeClassDesc coclass in _classes) {
  153. if (member == coclass.TypeName) {
  154. return true;
  155. }
  156. }
  157. if (_enums.ContainsKey(member) == true)
  158. return true;
  159. return false;
  160. }
  161. public Guid Guid {
  162. get { return _typeLibAttributes.guid; }
  163. }
  164. public short VersionMajor {
  165. get { return _typeLibAttributes.wMajorVerNum; }
  166. }
  167. public short VersionMinor {
  168. get { return _typeLibAttributes.wMinorVerNum; }
  169. }
  170. public string Name {
  171. get { return _typeLibName; }
  172. }
  173. internal ComTypeClassDesc GetCoClassForInterface(string itfName) {
  174. foreach (ComTypeClassDesc coclass in _classes) {
  175. if (coclass.Implements(itfName, false)) {
  176. return coclass;
  177. }
  178. }
  179. return null;
  180. }
  181. }
  182. }
  183. #endif