// Get a classinfo when reading from the registry internal static ComClassInfo GetClassInfo(RegistryKey classKey, String guidStr) { Guid guid = new Guid(guidStr); ComClassInfo clsInfo = (ComClassInfo)_classesByCLSID[guid]; if (clsInfo != null) { return(clsInfo); } return(new ComClassInfo(classKey, guidStr)); }
protected Type GetTypeFromTypeLib(TypeLibrary typeLib) { if (typeLib == null) { _typeFailedException = new Exception("Unable to determine TypeLib " + "from CLSID: " + _guidStr); throw _typeFailedException; } // Set this information because we might have read the // class from a source other than the type library _container = typeLib; _typeLib = typeLib; // Get the type associated with the CLSId from the typelib if (Name == null) { ComClassInfo clsInfo = typeLib.GetClassInfoFromCLSID(_guid); Name = clsInfo.Name; } Type type = typeLib.FindTypeByName(Name, TypeLibrary.FIND_CLASS); if (type == null) { _typeFailedException = new Exception("CLR type not found in " + _container + " for ActiveX type " + this + ".\n\nThis is likely caused by " + "the assembly corresponding to " + "this type library not being " + "available."); throw _typeFailedException; } if (TraceUtil.If(this, TraceLevel.Info)) { Trace.WriteLine("ComClassInfo - type: " + type); } return(type); }
// Returns a ComClassInfo for the requested class // Used for creating from within a typelib internal static ComClassInfo GetClassInfo(TypeLibrary typeLib, TYPEKIND typeKind, int index) { UCOMITypeInfo typeInfo; typeLib.ITypeLib.GetTypeInfo(index, out typeInfo); Guid guid = GuidFromTypeInfo(typeInfo); ComClassInfo clsInfo = (ComClassInfo)_classesByCLSID[guid]; if (clsInfo != null) { // Add the type lib information if we have seen this // class before clsInfo.SetupTypeLibInfo(typeLib, typeKind, index, null, Guid.Empty); return(clsInfo); } return(new ComClassInfo(typeLib, typeKind, index, typeInfo, guid)); }
// Figures out the class Type of an object based on the // information in this type library // This is presently not used, we call GetTypeForITypeInfo // instead. But let's keep this around since it might // be valuable to get a COM class instead of interface internal Type FigureOutClass() { _interfaces = new ArrayList(); IntPtr unkPtr = Marshal.GetIUnknownForObject(_obj); Marshal.AddRef(unkPtr); // Find out all if the interfaces in the library implemented // by the object foreach (ComInterfaceInfo intInfo in _typeLib.Interfaces) { Guid tempGuid = intInfo._guid; IntPtr implPtr; Marshal.QueryInterface(unkPtr, ref tempGuid, out implPtr); if (implPtr != IntPtr.Zero) { if (TraceUtil.If(this, TraceLevel.Info)) { Trace.WriteLine("ComObjectInfo - impl IID: " + intInfo); } // Makes sure we have the type information for this interface // This method has been removed from ComInterfaceInfo // since its only used here //intInfo.ResolveInterface(); _interfaces.Add(intInfo); } } Marshal.Release(unkPtr); // Find out if any classes have default interfaces of any // of the interfaces implemented, hopefully there will be // only one _classesDefaultInterfaces = new ArrayList(); _classesInterfaces = new ArrayList(); foreach (ComInterfaceInfo intInfo in _interfaces) { if (TraceUtil.If(this, TraceLevel.Info)) { Trace.WriteLine("ComObjectInfo - checking IID: " + intInfo); } //foreach (ComClassInfo classInfo in intInfo._typeLib.Classes) foreach (ComClassInfo classInfo in ComClassInfo.GetClassInfos(intInfo)) { if (TraceUtil.If(this, TraceLevel.Info)) { Trace.WriteLine("TypeLib - checking class: " + classInfo); } if (classInfo._defaultInterface == null) { continue; } if (classInfo._defaultInterface.Equals(intInfo)) { _classesDefaultInterfaces.Add(classInfo); } // Note that this does not consider the inherited // interfaces, but that's probably for the best now // We want to consider those only after we have // exhausted all over possibilities foreach (ComInterfaceInfo implIface in classInfo._interfaces) { if (implIface.Equals(intInfo)) { _classesInterfaces.Add(classInfo); } } } } /***** * FIXME - stuff to do to finish this: * 1) make a hash table that has all classes that implement a given interface. * Probably make a class/interface into structure that is a list from this * hash table. This has an indication if its the classes default interface * or not. Sometimes you will get an interface in one typelib and the class * is in another type lib. This will help that, and it will also make * the resolution of the classes faster. * 2) deal with inherited interfaces. After we have exhausted all * possbilities with the actual interfaces, when we should do checking * using the inherited interfaces so at least we will find something. * Of course, the inherited interfaces will show up on the query interface, * so we need to make sure we prefer the lower level interfaces. Maybe * they will always show up first, but we need to see about this. *****/ // If no default interface, then just take the first class // that implements this interface BasicInfo chosenClass; if (_classesDefaultInterfaces.Count > 0) { chosenClass = (BasicInfo)_classesDefaultInterfaces[0]; if (TraceUtil.If(this, TraceLevel.Info)) { Trace.WriteLine("ComObjectInfo - FOUND default i/f: " + chosenClass); } } else if (_classesInterfaces.Count > 0) { chosenClass = (BasicInfo)_classesInterfaces[0]; if (TraceUtil.If(this, TraceLevel.Info)) { Trace.WriteLine("ComObjectInfo - FOUND non-default i/f: " + chosenClass); } } else if (_interfaces.Count == 1) { chosenClass = (BasicInfo)_interfaces[0]; if (TraceUtil.If(this, TraceLevel.Info)) { Trace.WriteLine("ComObjectInfo - FOUND only one interface: " + chosenClass); } } else { if (TraceUtil.If(this, TraceLevel.Info)) { Trace.WriteLine("ComObjectInfo - NO CLASS FOUND " + " (using static): " + this); } SetStaticType(); return(_objTypeStatic); } String className = chosenClass._container.Name + "." + chosenClass.Name; if (chosenClass is ComClassInfo) { className += "Class"; } Type t = Type.GetType(className + "," + _typeLib.Name, true, true); if (TraceUtil.If(this, TraceLevel.Info)) { Trace.WriteLine("ComObjectInfo - FOUND type: " + t); } return(t); // This does not seem to work //return Type.GetTypeFromCLSID // (((ComClassInfo)_classesDefaultInterfaces[0])._guid, true); }
// We have an object and we want to figure out the best // type for it protected override void SetType() { if (TraceUtil.If(this, TraceLevel.Info)) { Trace.WriteLine("ComObjInfo - SetType: " + _obj); } if (_obj != null) { if (!_obj.GetType().IsCOMObject&& !_obj.GetType().Equals(Windows.COM_ROOT_TYPE)) { base.SetType(); return; } if (TypeIsGoodEnough(_obj.GetType())) { _objType = _obj.GetType(); return; } } if (TypeIsGoodEnough(_objType)) { return; } // Get the type library so we can convert it only once. If // we don't do this, the GetTypeForITypeInfo code will // try to convert it multiple times. This also sets the _typeInfo // pointer. if (_typeLib == null) { IntPtr dispPtr; // Get the IDispatch ptr try { dispPtr = Marshal.GetIDispatchForObject(_obj); } catch { // This could just be a COM object, see if it // implements any of the interfaces we know about _interfaces = ComInterfaceInfo.GetImplementedInterfacesKnown(_obj); if (_interfaces.Count == 0) { throw new Exception ("Unable to determine type of object, " + "IDispatch not implemented, and it implements " + "no interfaces associated with known type " + "libraries."); } ComInterfaceInfo ciInfo = PickBestInterface(); AssignType(ciInfo.GetCLRType()); return; } // Get the type library from the dispPtr try { Marshal.AddRef(dispPtr); GetTypeLib(dispPtr); } finally { Marshal.Release(dispPtr); } } if (_typeLib != null) { // Get the COM pointer to the ITypeInfo so we can call // GetTypeForITypeInfo below. //IntPtr iTypeInfo = Marshal.GetIUnknownForObject(_typeInfo); // This figures out the actual class of the object, by hand // based on what interfaces it implements. //Type newType = FigureOutClass(); // This returns the type of the interface this object implements, // but is done completely automatically. This is probably the // better solution (since is less of my code). // The problem this this one is that it converts any // necessary type libraries automatically without // having my hooks so I can properly find out about the // converted type libraries //Type newType = Marshal.GetTypeForITypeInfo(iTypeInfo); // Just look up the type by name from the type info's name, // this will get an interface type, which is fine. A class type // might be better, but that takes more work to figure out. // FIXME - we may want to go to find the class type for those // objects that implement multiple interfaces, see about that. String typeName = ComClassInfo.GetTypeName(_typeInfo); _comTypeName = _typeLib.Name + "." + typeName; if (TraceUtil.If(this, TraceLevel.Info)) { Trace.WriteLine("TypeName: " + typeName); } Type newType = _typeLib.FindTypeByName(typeName, !TypeLibrary.FIND_CLASS); AssignType(newType); } // Can't figure it out, let the superclass deal with it if (_objType == null) { base.SetType(); } }
// Applies to classes and interface, and since we don't have // a common superclass, just put it here and make it static internal static CodeTypeDeclaration CreateTypeCodeDom (BasicInfo basicInfo, ArrayList interfaces, bool doClass) { CodeTypeDeclaration codeDom = new CodeTypeDeclaration(); Guid useGuid = basicInfo._guid; if (basicInfo is ComClassInfo && doClass) { codeDom.Name = basicInfo.Name + "Class"; codeDom.IsInterface = false; } else { // Use the default interface's class if we are generating // the interface for the class if (basicInfo is ComClassInfo) { useGuid = ((ComClassInfo)basicInfo).DefaultInterface._guid; } codeDom.Name = basicInfo.Name; codeDom.IsInterface = true; if (basicInfo is ComInterfaceInfo) { ComInterfaceInfo ifaceInfo = (ComInterfaceInfo)basicInfo; ComInterfaceType ifaceType; if (ifaceInfo._dual) { ifaceType = ComInterfaceType.InterfaceIsDual; } else if (ifaceInfo._dispatch) { ifaceType = ComInterfaceType.InterfaceIsIDispatch; } else { ifaceType = ComInterfaceType.InterfaceIsIUnknown; } // Add InterfaceType attribute CodeAttributeArgument ifaceTypeArg = new CodeAttributeArgument(); ifaceTypeArg.Value = new CodeSnippetExpression ("(System.Runtime.InteropServices.ComInterfaceType)" + (int)ifaceType); codeDom.CustomAttributes.Add (new CodeAttributeDeclaration ("System.Runtime.InteropServices.InterfaceType", new CodeAttributeArgument[] { ifaceTypeArg })); } } // Add Guid attribute CodeAttributeArgument guidArg = new CodeAttributeArgument(); // The _guidStr has braces which the attribute can't handle guidArg.Value = new CodePrimitiveExpression (useGuid.ToString()); codeDom.CustomAttributes.Add (new CodeAttributeDeclaration ("System.Runtime.InteropServices.Guid", new CodeAttributeArgument[] { guidArg })); if (basicInfo is ComClassInfo) { ComClassInfo classInfo = (ComClassInfo)basicInfo; if (doClass) { codeDom.TypeAttributes |= TypeAttributes.Abstract; // Class inherits from the interface of the same name codeDom.BaseTypes.Add (new CodeTypeReference(basicInfo.Name)); // Add TypeLibType attribute CodeAttributeArgument typeLibTypeArg = new CodeAttributeArgument(); typeLibTypeArg.Value = new CodePrimitiveExpression ((int)classInfo._typeFlags); codeDom.CustomAttributes.Add (new CodeAttributeDeclaration ("System.Runtime.InteropServices.TypeLibType", new CodeAttributeArgument[] { typeLibTypeArg })); // Add ClassInterface attribute CodeAttributeArgument classIfaceArg = new CodeAttributeArgument(); classIfaceArg.Value = new CodeSnippetExpression("(short)0"); codeDom.CustomAttributes.Add (new CodeAttributeDeclaration ("System.Runtime.InteropServices.ClassInterface", new CodeAttributeArgument[] { classIfaceArg })); // Make the no-arg constructor public (default cons // visibility is family) CodeConstructor cons = new CodeConstructor(); cons.Attributes = MemberAttributes.Public; codeDom.Members.Add(cons); } else { // Add CoClass attribute CodeAttributeArgument typeArg = new CodeAttributeArgument(); typeArg.Value = new CodeTypeReferenceExpression (new CodeTypeReference("typeof(" + basicInfo.GetCLRTypeName() + ")")); codeDom.CustomAttributes.Add (new CodeAttributeDeclaration ("System.Runtime.InteropServices.CoClass", new CodeAttributeArgument[] { typeArg })); } } if (TraceUtil.If(basicInfo, TraceLevel.Info)) { Trace.WriteLine(basicInfo, "CG - " + basicInfo.Name); } bool firstTime = true; // Add inherited interfaces foreach (BasicInfo member in interfaces) { if (member is ComInterfaceInfo) { // FIXME - should probably compare these by GUID if (member.Name.Equals("IUnknown") || member.Name.Equals("IDispatch")) { continue; } codeDom.BaseTypes.Add (new CodeTypeReference(member.Name)); // Add the members for the class or interface, // its all of the members // of each implemented interface if ((!codeDom.IsInterface && doClass) || codeDom.IsInterface) { // Qualify subsequent interfaces with the // interface name // Unless this is an interface, then just // leave the name alone if (firstTime || codeDom.IsInterface) { AddMembers(codeDom, member.Members, null); } else { AddMembers(codeDom, member.Members, member.Name + "_"); } } firstTime = false; } } // Don't add the members for the class interface if (basicInfo is ComClassInfo && !doClass) { return(codeDom); } // Add members for this interface (a class has none) AddMembers(codeDom, basicInfo.Members, null); return(codeDom); }