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