MegaBites-AI/Windows-powershell
0372
1// Licensed to the .NET Foundation under one or more agreements.2// The .NET Foundation licenses this file to you under the MIT license.3 4using System;5using System.Collections.Generic;6using System.Dynamic;7using System.Globalization;8using System.Linq.Expressions;9using System.Runtime.InteropServices;10using ComTypes = System.Runtime.InteropServices.ComTypes;11 12namespace System.Management.Automation.ComInterop13{14 /// <summary>15 /// Cached information from a TLB. Only information that is required is saved. CoClasses are used16 /// for event hookup. Enums are stored for accessing symbolic names from scripts.17 /// </summary>18 internal sealed class ComTypeLibDesc : IDynamicMetaObjectProvider19 {20 // typically typelibs contain very small number of coclasses21 // so we will just use the linked list as it performs better22 // on small number of entities23 private readonly LinkedList<ComTypeClassDesc> _classes;24 private readonly Dictionary<string, ComTypeEnumDesc> _enums;25 private ComTypes.TYPELIBATTR _typeLibAttributes;26 27 private static readonly Dictionary<Guid, ComTypeLibDesc> s_cachedTypeLibDesc = new Dictionary<Guid, ComTypeLibDesc>();28 29 private ComTypeLibDesc()30 {31 _enums = new Dictionary<string, ComTypeEnumDesc>();32 _classes = new LinkedList<ComTypeClassDesc>();33 }34 35 public override string ToString() => $"<type library {Name}>";36 37 public string Documentation38 {39 get { return string.Empty; }40 }41 42 #region IDynamicMetaObjectProvider Members43 44 DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter)45 {46 return new TypeLibMetaObject(parameter, this);47 }48 49 #endregion50 51 internal static ComTypeLibDesc GetFromTypeLib(ComTypes.ITypeLib typeLib)52 {53 // check whether we have already loaded this type library54 ComTypes.TYPELIBATTR typeLibAttr = ComRuntimeHelpers.GetTypeAttrForTypeLib(typeLib);55 ComTypeLibDesc typeLibDesc;56 lock (s_cachedTypeLibDesc)57 {58 if (s_cachedTypeLibDesc.TryGetValue(typeLibAttr.guid, out typeLibDesc))59 {60 return typeLibDesc;61 }62 }63 64 typeLibDesc = new ComTypeLibDesc65 {66 Name = ComRuntimeHelpers.GetNameOfLib(typeLib),67 _typeLibAttributes = typeLibAttr68 };69 70 int countTypes = typeLib.GetTypeInfoCount();71 for (int i = 0; i < countTypes; i++)72 {73 typeLib.GetTypeInfoType(i, out ComTypes.TYPEKIND typeKind);74 75 typeLib.GetTypeInfo(i, out ComTypes.ITypeInfo typeInfo);76 if (typeKind == ComTypes.TYPEKIND.TKIND_COCLASS)77 {78 ComTypeClassDesc classDesc = new ComTypeClassDesc(typeInfo, typeLibDesc);79 typeLibDesc._classes.AddLast(classDesc);80 }81 else if (typeKind == ComTypes.TYPEKIND.TKIND_ENUM)82 {83 ComTypeEnumDesc enumDesc = new ComTypeEnumDesc(typeInfo, typeLibDesc);84 typeLibDesc._enums.Add(enumDesc.TypeName, enumDesc);85 }86 else if (typeKind == ComTypes.TYPEKIND.TKIND_ALIAS)87 {88 ComTypes.TYPEATTR typeAttr = ComRuntimeHelpers.GetTypeAttrForTypeInfo(typeInfo);89 if (typeAttr.tdescAlias.vt == (short)VarEnum.VT_USERDEFINED)90 {91 ComRuntimeHelpers.GetInfoFromType(typeInfo, out string aliasName, out _);92 93 typeInfo.GetRefTypeInfo(typeAttr.tdescAlias.lpValue.ToInt32(), out ComTypes.ITypeInfo referencedTypeInfo);94 95 ComTypes.TYPEATTR referencedTypeAttr = ComRuntimeHelpers.GetTypeAttrForTypeInfo(referencedTypeInfo);96 ComTypes.TYPEKIND referencedTypeKind = referencedTypeAttr.typekind;97 98 if (referencedTypeKind == ComTypes.TYPEKIND.TKIND_ENUM)99 {100 ComTypeEnumDesc enumDesc = new ComTypeEnumDesc(referencedTypeInfo, typeLibDesc);101 typeLibDesc._enums.Add(aliasName, enumDesc);102 }103 }104 }105 }106 107 // cached the typelib using the guid as the dictionary key108 lock (s_cachedTypeLibDesc)109 {110 s_cachedTypeLibDesc.Add(typeLibAttr.guid, typeLibDesc);111 }112 113 return typeLibDesc;114 }115 116 public object GetTypeLibObjectDesc(string member)117 {118 foreach (ComTypeClassDesc coclass in _classes)119 {120 if (member == coclass.TypeName)121 {122 return coclass;123 }124 }125 126 if (_enums != null && _enums.TryGetValue(member, out ComTypeEnumDesc enumDesc))127 return enumDesc;128 129 return null;130 }131 132 public string[] GetMemberNames()133 {134 string[] retval = new string[_enums.Count + _classes.Count];135 int i = 0;136 foreach (ComTypeClassDesc coclass in _classes)137 {138 retval[i++] = coclass.TypeName;139 }140 141 foreach (KeyValuePair<string, ComTypeEnumDesc> enumDesc in _enums)142 {143 retval[i++] = enumDesc.Key;144 }145 146 return retval;147 }148 149 internal bool HasMember(string member)150 {151 foreach (ComTypeClassDesc coclass in _classes)152 {153 if (member == coclass.TypeName)154 {155 return true;156 }157 }158 159 if (_enums.ContainsKey(member))160 return true;161 162 return false;163 }164 165 public Guid Guid => _typeLibAttributes.guid;166 167 public string Name { get; private set; }168 169 internal ComTypeClassDesc GetCoClassForInterface(string itfName)170 {171 foreach (ComTypeClassDesc coclass in _classes)172 {173 if (coclass.Implements(itfName, false))174 {175 return coclass;176 }177 }178 179 return null;180 }181 }182}183 