// Get or create a interface info for the specified interface internal static ComInterfaceInfo GetInterfaceInfo (TypeLibrary typeLib, TYPEKIND typeKind, int index) { UCOMITypeInfo typeInfo; Guid guid; typeLib.ITypeLib.GetTypeInfo(index, out typeInfo); guid = GuidFromTypeInfo(typeInfo); // Use the TypeLibrary lock to prevent deadlocks lock (typeof(TypeLibrary)) { // Never heard of it, get the defining type library ComInterfaceInfo intInfo = (ComInterfaceInfo)_interfacesByGuid[guid]; if (intInfo == null) { // Add the interface to the table before we call // setup because setup will try to create the // inherited interfaces, and it should find // this one (otherwise it will stack overflow) intInfo = new ComInterfaceInfo(); _interfacesByGuid.Add(guid, intInfo); intInfo.Setup(typeLib, typeKind, index); } return(intInfo); } }
// Finds the best class that implements this interface internal static ArrayList GetClassInfos(ComInterfaceInfo intInfo) { // Add to the global hash lock (_classesByInterface) { ArrayList ret = (ArrayList)_classesByInterface[intInfo]; if (ret == null) { return(new ArrayList()); } return(ret); } }
protected ComInterfaceInfo PickBestInterface() { ComInterfaceInfo bestIf = null; // Pick the one with the highest number of parents foreach (ComInterfaceInfo ifInfo in _interfaces) { if (bestIf == null || ifInfo.ParentCount > bestIf.ParentCount) { bestIf = ifInfo; } } return(bestIf); }
public override void AddDomTo(IList parent) { //return; // Do the class CodeTypeDeclaration codeDom = ComInterfaceInfo.CreateTypeCodeDom (this, _interfaces, ComInterfaceInfo.DOCLASS); parent.Add(codeDom); // Do the interface associated with the class codeDom = ComInterfaceInfo.CreateTypeCodeDom (this, _interfaces, !ComInterfaceInfo.DOCLASS); parent.Add(codeDom); }
internal void AddInterface(ComInterfaceInfo intInfo, bool isDefault) { _interfaces.Add(intInfo); if (isDefault) { _defaultInterface = intInfo; } // Add to the global hash lock (_classesByInterface) { ArrayList classList = (ArrayList)_classesByInterface[intInfo]; if (classList == null) { classList = new ArrayList(); _classesByInterface.Add(intInfo, classList); } classList.Add(this); } }
// Get or create a interface info for the specified interface internal static ComInterfaceInfo GetInterfaceInfo (TypeLibrary typeLib, TYPEKIND typeKind, int index) { UCOMITypeInfo typeInfo; Guid guid; typeLib.ITypeLib.GetTypeInfo(index, out typeInfo); guid = GuidFromTypeInfo(typeInfo); // Use the TypeLibrary lock to prevent deadlocks lock (typeof(TypeLibrary)) { // Never heard of it, get the defining type library ComInterfaceInfo intInfo = (ComInterfaceInfo)_interfacesByGuid[guid]; if (intInfo == null) { // Add the interface to the table before we call // setup because setup will try to create the // inherited interfaces, and it should find // this one (otherwise it will stack overflow) intInfo = new ComInterfaceInfo(); _interfacesByGuid.Add(guid, intInfo); intInfo.Setup(typeLib, typeKind, index); } return intInfo; } }
// 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(); } }
// Finds the best class that implements this interface internal static ArrayList GetClassInfos(ComInterfaceInfo intInfo) { // Add to the global hash lock (_classesByInterface) { ArrayList ret = (ArrayList)_classesByInterface[intInfo]; if (ret == null) return new ArrayList(); return ret; } }
internal void AddInterface(ComInterfaceInfo intInfo, bool isDefault) { _interfaces.Add(intInfo); if (isDefault) _defaultInterface = intInfo; // Add to the global hash lock (_classesByInterface) { ArrayList classList = (ArrayList)_classesByInterface[intInfo]; if (classList == null) { classList = new ArrayList(); _classesByInterface.Add(intInfo, classList); } classList.Add(this); } }
// 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); }
// Constructor from creating withing a typelib internal override void Setup(TypeLibrary typeLib, TYPEKIND typeKind, int index) { base.Setup(typeLib, typeKind, index); Init(); _container = typeLib; TYPEATTR typeAttr; IntPtr typeAttrPtr; _typeInfo.GetTypeAttr(out typeAttrPtr); typeAttr = (TYPEATTR)Marshal.PtrToStructure(typeAttrPtr, typeof(TYPEATTR)); if (typeKind == TYPEKIND.TKIND_DISPATCH) { _infoType = "Dispatch Interface"; _dispatch = true; } else { _infoType = "Interface"; } if ((typeAttr.wTypeFlags & TYPEFLAGS.TYPEFLAG_FDUAL) != 0) { _infoType = "Dual Interface"; _dispatch = true; _dual = true; } // Members for (int i = 0; i < typeAttr.cFuncs; i++) { // Some members for a dispatch interface are not added // because they are the inherited members from the // IDispatch interface ComMemberInfo mi = ComMemberInfo. MakeComMemberInfo(this, typeKind, _typeInfo, i, _dispatch, _dual); if (mi != null) { _members.Add(mi); _memberNames.Add(mi.NameKey, mi); } } // Inherited interfaces for (int i = 0; i < typeAttr.cImplTypes; i++) { int href; int refTypeIndex; UCOMITypeInfo refTypeInfo; UCOMITypeLib refITypeLib; TypeLibrary refTypeLib; try { _typeInfo.GetRefTypeOfImplType(i, out href); _typeInfo.GetRefTypeInfo(href, out refTypeInfo); refTypeInfo.GetContainingTypeLib(out refITypeLib, out refTypeIndex); refTypeLib = TypeLibrary.GetTypeLib(refITypeLib); ComInterfaceInfo mi = ComInterfaceInfo.GetInterfaceInfo(refTypeLib, typeAttr.typekind, refTypeIndex); if (TraceUtil.If(this, TraceLevel.Verbose)) { Trace.WriteLine(" inherit: " + mi); } _members.Add(mi); _parentCount += 1 + mi.ParentCount; // Don't set the typelib on the member as multiple // typelibs may refer to the same interface mi._container = this; } catch (Exception ex) { ErrorDialog.Show (ex, "Warning - this error was detected when attempting " + "to find an ancestor of the interface " + _name + ". This is normal in the case where the type " + "library containing that interface " + "is not available. " + "In other situations this might be a bug and " + "should be reported.", "Warning - Cannot Access Inherited Interface", MessageBoxIcon.Warning); } } if (_dual) { _printName = (String)_name.Clone(); _printName += " (Dual)"; } else { _printName = _name; } _typeInfo.ReleaseTypeAttr(typeAttrPtr); }