internal static COM.FUNCDESC GetFuncDesc(COM.ITypeInfo typeinfo, int index) { IntPtr pFuncDesc; typeinfo.GetFuncDesc(index, out pFuncDesc); COM.FUNCDESC funcdesc = Marshal.PtrToStructure <COM.FUNCDESC>(pFuncDesc); typeinfo.ReleaseFuncDesc(pFuncDesc); return(funcdesc); }
private static IEnumerable <ComTypes.FUNCDESC> GetFuncDescs(ComTypes.ITypeInfo typeInfo, ComTypes.TYPEATTR typeAttr) { for (var iFunc = 0; iFunc < typeAttr.cFuncs; iFunc++) { IntPtr pFuncDesc; typeInfo.GetFuncDesc(iFunc, out pFuncDesc); var funcDesc = (ComTypes.FUNCDESC)Marshal.PtrToStructure(pFuncDesc, typeof(ComTypes.FUNCDESC)); yield return(funcDesc); typeInfo.ReleaseFuncDesc(pFuncDesc); } }
private static void ScanSourceInterface(ComTypes.ITypeInfo sourceTypeInfo, ref Dictionary <string, ComEventDesc> events) { ComTypes.TYPEATTR sourceTypeAttribute = ComRuntimeHelpers.GetTypeAttrForTypeInfo(sourceTypeInfo); for (int index = 0; index < sourceTypeAttribute.cFuncs; index++) { IntPtr funcDescHandleToRelease = IntPtr.Zero; try { ComTypes.FUNCDESC funcDesc; GetFuncDescForDescIndex(sourceTypeInfo, index, out funcDesc, out funcDescHandleToRelease); // we are not interested in hidden or restricted functions for now. if ((funcDesc.wFuncFlags & (int)ComTypes.FUNCFLAGS.FUNCFLAG_FHIDDEN) != 0) { continue; } if ((funcDesc.wFuncFlags & (int)ComTypes.FUNCFLAGS.FUNCFLAG_FRESTRICTED) != 0) { continue; } string name = ComRuntimeHelpers.GetNameOfMethod(sourceTypeInfo, funcDesc.memid); name = name.ToUpper(System.Globalization.CultureInfo.InvariantCulture); // Sometimes coclass has multiple source interfaces. Usually this is caused by // adding new events and putting them on new interfaces while keeping the // old interfaces around. This may cause name collisions which we are // resolving by keeping only the first event with the same name. if (events.ContainsKey(name) == false) { ComEventDesc eventDesc = new ComEventDesc(); eventDesc.dispid = funcDesc.memid; eventDesc.sourceIID = sourceTypeAttribute.guid; events.Add(name, eventDesc); } } finally { if (funcDescHandleToRelease != IntPtr.Zero) { sourceTypeInfo.ReleaseFuncDesc(funcDescHandleToRelease); } } } }
/// <summary> /// Converts a MethodBase[] into a MethodInformation[] /// </summary> /// <returns>the ComMethodInformation[] corresponding to methods</returns> internal static ComMethodInformation[] GetMethodInformationArray(COM.ITypeInfo typeInfo, Collection <int> methods, bool skipLastParameters) { int methodCount = methods.Count; int count = 0; ComMethodInformation[] returnValue = new ComMethodInformation[methodCount]; foreach (int index in methods) { IntPtr pFuncDesc; typeInfo.GetFuncDesc(index, out pFuncDesc); COM.FUNCDESC funcdesc = ClrFacade.PtrToStructure <COM.FUNCDESC>(pFuncDesc); returnValue[count++] = ComUtil.GetMethodInformation(funcdesc, skipLastParameters); typeInfo.ReleaseFuncDesc(pFuncDesc); } return(returnValue); }
internal string GetDefinition() { IntPtr pFuncDesc = IntPtr.Zero; try { _typeInfo.GetFuncDesc(GetFuncDescIndex(), out pFuncDesc); COM.FUNCDESC funcdesc = Marshal.PtrToStructure <COM.FUNCDESC>(pFuncDesc); return(ComUtil.GetMethodSignatureFromFuncDesc(_typeInfo, funcdesc, !IsGettable)); } finally { if (pFuncDesc != IntPtr.Zero) { _typeInfo.ReleaseFuncDesc(pFuncDesc); } } }
/// <summary> /// Returns the different method overloads signatures. /// </summary> /// <returns></returns> internal Collection <string> MethodDefinitions() { Collection <string> result = new Collection <string>(); foreach (int index in _methods) { IntPtr pFuncDesc; _typeInfo.GetFuncDesc(index, out pFuncDesc); COM.FUNCDESC funcdesc = Marshal.PtrToStructure <COM.FUNCDESC>(pFuncDesc); string signature = ComUtil.GetMethodSignatureFromFuncDesc(_typeInfo, funcdesc, false); result.Add(signature); _typeInfo.ReleaseFuncDesc(pFuncDesc); } return(result); }
private void EnsureScanDefinedMethods() { if (_comTypeDesc != null && _comTypeDesc.Funcs != null) { return; } // // Demand Full Trust to proceed with the operation. // new PermissionSet(PermissionState.Unrestricted).Demand(); ComTypes.ITypeInfo typeInfo = ComRuntimeHelpers.GetITypeInfoFromIDispatch(_dispatchObject, true); if (typeInfo == null) { _comTypeDesc = ComTypeDesc.CreateEmptyTypeDesc(); return; } ComTypes.TYPEATTR typeAttr = ComRuntimeHelpers.GetTypeAttrForTypeInfo(typeInfo); if (_comTypeDesc == null) { lock (_CacheComTypeDesc) { if (_CacheComTypeDesc.TryGetValue(typeAttr.guid, out _comTypeDesc) == true && _comTypeDesc.Funcs != null) { return; } } } ComTypeDesc typeDesc = ComTypeDesc.FromITypeInfo(typeInfo, typeAttr); ComMethodDesc getItem = null; ComMethodDesc setItem = null; Hashtable funcs = new Hashtable(typeAttr.cFuncs); Hashtable puts = new Hashtable(); Hashtable putrefs = new Hashtable(); for (int definedFuncIndex = 0; definedFuncIndex < typeAttr.cFuncs; definedFuncIndex++) { IntPtr funcDescHandleToRelease = IntPtr.Zero; try { ComTypes.FUNCDESC funcDesc; GetFuncDescForDescIndex(typeInfo, definedFuncIndex, out funcDesc, out funcDescHandleToRelease); if ((funcDesc.wFuncFlags & (int)ComTypes.FUNCFLAGS.FUNCFLAG_FRESTRICTED) != 0) { // This function is not meant for the script user to use. continue; } ComMethodDesc method = new ComMethodDesc(typeInfo, funcDesc); string name = method.Name.ToUpper(System.Globalization.CultureInfo.InvariantCulture); if ((funcDesc.invkind & ComTypes.INVOKEKIND.INVOKE_PROPERTYPUT) != 0) { puts.Add(name, method); // for the special dispId == 0, we need to store // the method descriptor for the Do(SetItem) binder. if (method.DispId == ComDispIds.DISPID_VALUE && setItem == null) { setItem = method; } continue; } if ((funcDesc.invkind & ComTypes.INVOKEKIND.INVOKE_PROPERTYPUTREF) != 0) { putrefs.Add(name, method); // for the special dispId == 0, we need to store // the method descriptor for the Do(SetItem) binder. if (method.DispId == ComDispIds.DISPID_VALUE && setItem == null) { setItem = method; } continue; } if (funcDesc.memid == ComDispIds.DISPID_NEWENUM) { funcs.Add("GETENUMERATOR", method); continue; } funcs.Add(name, method); // for the special dispId == 0, we need to store the method descriptor // for the Do(GetItem) binder. if (funcDesc.memid == ComDispIds.DISPID_VALUE) { getItem = method; } } finally { if (funcDescHandleToRelease != IntPtr.Zero) { typeInfo.ReleaseFuncDesc(funcDescHandleToRelease); } } } lock (_CacheComTypeDesc) { ComTypeDesc cachedTypeDesc; if (_CacheComTypeDesc.TryGetValue(typeAttr.guid, out cachedTypeDesc)) { _comTypeDesc = cachedTypeDesc; } else { _comTypeDesc = typeDesc; _CacheComTypeDesc.Add(typeAttr.guid, _comTypeDesc); } _comTypeDesc.Funcs = funcs; _comTypeDesc.Puts = puts; _comTypeDesc.PutRefs = putrefs; _comTypeDesc.EnsureGetItem(getItem); _comTypeDesc.EnsureSetItem(setItem); } }
private void EnsureScanDefinedMethods() { if (_comTypeDesc != null && _comTypeDesc.Funcs != null) { return; } ComTypes.ITypeInfo typeInfo = ComRuntimeHelpers.GetITypeInfoFromIDispatch(DispatchObject, true); if (typeInfo == null) { _comTypeDesc = ComTypeDesc.CreateEmptyTypeDesc(); return; } ComTypes.TYPEATTR typeAttr = ComRuntimeHelpers.GetTypeAttrForTypeInfo(typeInfo); if (_comTypeDesc == null) { lock (s_cacheComTypeDesc) { if (s_cacheComTypeDesc.TryGetValue(typeAttr.guid, out _comTypeDesc) == true && _comTypeDesc.Funcs != null) { return; } } } if (typeAttr.typekind == ComTypes.TYPEKIND.TKIND_INTERFACE) { // We have typeinfo for custom interface. Get typeinfo for Dispatch interface. typeInfo = ComTypeInfo.GetDispatchTypeInfoFromCustomInterfaceTypeInfo(typeInfo); typeAttr = ComRuntimeHelpers.GetTypeAttrForTypeInfo(typeInfo); } if (typeAttr.typekind == ComTypes.TYPEKIND.TKIND_COCLASS) { // We have typeinfo for the COClass. Find the default interface and get typeinfo for default interface. typeInfo = ComTypeInfo.GetDispatchTypeInfoFromCoClassTypeInfo(typeInfo); typeAttr = ComRuntimeHelpers.GetTypeAttrForTypeInfo(typeInfo); } ComTypeDesc typeDesc = ComTypeDesc.FromITypeInfo(typeInfo, typeAttr); ComMethodDesc getItem = null; ComMethodDesc setItem = null; Hashtable funcs = new Hashtable(typeAttr.cFuncs); Hashtable puts = new Hashtable(); Hashtable putrefs = new Hashtable(); for (int definedFuncIndex = 0; definedFuncIndex < typeAttr.cFuncs; definedFuncIndex++) { IntPtr funcDescHandleToRelease = IntPtr.Zero; try { ComTypes.FUNCDESC funcDesc; GetFuncDescForDescIndex(typeInfo, definedFuncIndex, out funcDesc, out funcDescHandleToRelease); if ((funcDesc.wFuncFlags & (int)ComTypes.FUNCFLAGS.FUNCFLAG_FRESTRICTED) != 0) { // This function is not meant for the script user to use. continue; } ComMethodDesc method = new ComMethodDesc(typeInfo, funcDesc); string name = method.Name.ToUpper(System.Globalization.CultureInfo.InvariantCulture); if ((funcDesc.invkind & ComTypes.INVOKEKIND.INVOKE_PROPERTYPUT) != 0) { // If there is a getter for this put, use that ReturnType as the // PropertyType. if (funcs.ContainsKey(name)) { method.InputType = ((ComMethodDesc)funcs[name]).ReturnType; } puts.Add(name, method); // for the special dispId == 0, we need to store // the method descriptor for the Do(SetItem) binder. if (method.DispId == ComDispIds.DISPID_VALUE && setItem == null) { setItem = method; } continue; } if ((funcDesc.invkind & ComTypes.INVOKEKIND.INVOKE_PROPERTYPUTREF) != 0) { // If there is a getter for this put, use that ReturnType as the // PropertyType. if (funcs.ContainsKey(name)) { method.InputType = ((ComMethodDesc)funcs[name]).ReturnType; } putrefs.Add(name, method); // for the special dispId == 0, we need to store // the method descriptor for the Do(SetItem) binder. if (method.DispId == ComDispIds.DISPID_VALUE && setItem == null) { setItem = method; } continue; } if (funcDesc.memid == ComDispIds.DISPID_NEWENUM) { funcs.Add("GETENUMERATOR", method); continue; } // If there is a setter for this put, update the InputType from our // ReturnType. if (puts.ContainsKey(name)) { ((ComMethodDesc)puts[name]).InputType = method.ReturnType; } if (putrefs.ContainsKey(name)) { ((ComMethodDesc)putrefs[name]).InputType = method.ReturnType; } funcs.Add(name, method); // for the special dispId == 0, we need to store the method descriptor // for the Do(GetItem) binder. if (funcDesc.memid == ComDispIds.DISPID_VALUE) { getItem = method; } } finally { if (funcDescHandleToRelease != IntPtr.Zero) { typeInfo.ReleaseFuncDesc(funcDescHandleToRelease); } } } lock (s_cacheComTypeDesc) { ComTypeDesc cachedTypeDesc; if (s_cacheComTypeDesc.TryGetValue(typeAttr.guid, out cachedTypeDesc)) { _comTypeDesc = cachedTypeDesc; } else { _comTypeDesc = typeDesc; s_cacheComTypeDesc.Add(typeAttr.guid, _comTypeDesc); } _comTypeDesc.Funcs = funcs; _comTypeDesc.Puts = puts; _comTypeDesc.PutRefs = putrefs; _comTypeDesc.EnsureGetItem(getItem); _comTypeDesc.EnsureSetItem(setItem); } }
/// <summary> /// Creates an entity support list for a proxy /// </summary> /// <param name="factory">core to perform searching</param> /// <param name="comProxy">proxy to analyze</param> /// <returns>supported methods and properties as name/kind dictionary</returns> /// <exception cref="COMException">Throws generaly if any exception occurs. See inner exception(s) for details</exception> internal Dictionary <string, string> GetSupportedEntities(Core factory, object comProxy) { try { Guid parentLibraryGuid = CoreFactoryExtensions.GetParentLibraryGuid(factory, comProxy); if (Guid.Empty == parentLibraryGuid) { return(null); } string className = TypeDescriptor.GetClassName(comProxy); string key = (parentLibraryGuid.ToString() + className).ToLower(); Dictionary <string, string> supportList = null; if (factory.EntitiesListCache.TryGetValue(key, out supportList)) { return(supportList); } supportList = new Dictionary <string, string>(); IDispatch dispatch = comProxy as IDispatch; if (null == dispatch) { throw new COMException("Unable to cast underlying proxy to IDispatch."); } COMTypes.ITypeInfo typeInfo = dispatch.GetTypeInfo(0, 0); if (null == typeInfo) { throw new COMException("GetTypeInfo returns null."); } IntPtr typeAttrPointer = IntPtr.Zero; typeInfo.GetTypeAttr(out typeAttrPointer); COMTypes.TYPEATTR typeAttr = (COMTypes.TYPEATTR)Marshal.PtrToStructure(typeAttrPointer, typeof(COMTypes.TYPEATTR)); for (int i = 0; i < typeAttr.cFuncs; i++) { string strName, strDocString, strHelpFile; int dwHelpContext; IntPtr funcDescPointer = IntPtr.Zero; COMTypes.FUNCDESC funcDesc; typeInfo.GetFuncDesc(i, out funcDescPointer); funcDesc = (COMTypes.FUNCDESC)Marshal.PtrToStructure(funcDescPointer, typeof(COMTypes.FUNCDESC)); switch (funcDesc.invkind) { case COMTypes.INVOKEKIND.INVOKE_PROPERTYGET: case COMTypes.INVOKEKIND.INVOKE_PROPERTYPUT: case COMTypes.INVOKEKIND.INVOKE_PROPERTYPUTREF: { typeInfo.GetDocumentation(funcDesc.memid, out strName, out strDocString, out dwHelpContext, out strHelpFile); string outValue = ""; bool exists = supportList.TryGetValue("Property-" + strName, out outValue); if (!exists) { supportList.Add("Property-" + strName, strDocString); } break; } case COMTypes.INVOKEKIND.INVOKE_FUNC: { typeInfo.GetDocumentation(funcDesc.memid, out strName, out strDocString, out dwHelpContext, out strHelpFile); string outValue = ""; bool exists = supportList.TryGetValue("Method-" + strName, out outValue); if (!exists) { supportList.Add("Method-" + strName, strDocString); } break; } } typeInfo.ReleaseFuncDesc(funcDescPointer); } typeInfo.ReleaseTypeAttr(typeAttrPointer); Marshal.ReleaseComObject(typeInfo); factory.EntitiesListCache.Add(key, supportList); return(supportList); } catch (Exception exception) { throw new COMException("An unexpected error occurs.", exception); } }
private void EnsureScanDefinedMethods() { if (_comTypeDesc != null && _comTypeDesc.Funcs != null) { return; } ComTypes.ITypeInfo typeInfo = ComRuntimeHelpers.GetITypeInfoFromIDispatch(_dispatchObject, true); if (typeInfo == null) { _comTypeDesc = ComTypeDesc.CreateEmptyTypeDesc(); return; } ComTypes.TYPEATTR typeAttr = ComRuntimeHelpers.GetTypeAttrForTypeInfo(typeInfo); if (_comTypeDesc == null) { lock (_CacheComTypeDesc) { if (_CacheComTypeDesc.TryGetValue(typeAttr.guid, out _comTypeDesc) == true && _comTypeDesc.Funcs != null) { return; } } } ComTypeDesc typeDesc = ComTypeDesc.FromITypeInfo(typeInfo); ComMethodDesc getItem = null; ComMethodDesc setItem = null; Dictionary <string, ComMethodDesc> funcs = new Dictionary <string, ComMethodDesc>(typeAttr.cFuncs); Dictionary <string, ComMethodDesc> puts = new Dictionary <string, ComMethodDesc>(); Dictionary <string, ComMethodDesc> putrefs = new Dictionary <string, ComMethodDesc>(); Set <int> usedDispIds = new Set <int>(); for (int definedFuncIndex = 0; definedFuncIndex < typeAttr.cFuncs; definedFuncIndex++) { IntPtr funcDescHandleToRelease = IntPtr.Zero; try { ComTypes.FUNCDESC funcDesc; GetFuncDescForDescIndex(typeInfo, definedFuncIndex, out funcDesc, out funcDescHandleToRelease); if ((funcDesc.wFuncFlags & (int)ComTypes.FUNCFLAGS.FUNCFLAG_FRESTRICTED) != 0) { // This function is not meant for the script user to use. continue; } ComMethodDesc method = new ComMethodDesc(typeInfo, funcDesc); if ((funcDesc.invkind & ComTypes.INVOKEKIND.INVOKE_PROPERTYPUT) != 0) { puts.Add(method.Name, method); continue; } if ((funcDesc.invkind & ComTypes.INVOKEKIND.INVOKE_PROPERTYPUTREF) != 0) { putrefs.Add(method.Name, method); continue; } usedDispIds.Add(funcDesc.memid); if (funcDesc.memid == ComDispIds.DISPID_NEWENUM) { funcs.Add("GetEnumerator", method); continue; } funcs.Add(method.Name, method); // for the special dispId == 0, we need to store the method descriptor // for the Do(GetItem) binder. if (funcDesc.memid == ComDispIds.DISPID_VALUE) { getItem = method; } } finally { if (funcDescHandleToRelease != IntPtr.Zero) { typeInfo.ReleaseFuncDesc(funcDescHandleToRelease); } } } ProcessPut(funcs, puts, usedDispIds, ref setItem); ProcessPut(funcs, putrefs, usedDispIds, ref setItem); lock (_CacheComTypeDesc) { ComTypeDesc cachedTypeDesc; if (_CacheComTypeDesc.TryGetValue(typeAttr.guid, out cachedTypeDesc)) { _comTypeDesc = cachedTypeDesc; } else { _comTypeDesc = typeDesc; _CacheComTypeDesc.Add(typeAttr.guid, _comTypeDesc); } _comTypeDesc.Funcs = funcs; _comTypeDesc.Puts = puts; _comTypeDesc.PutRefs = putrefs; _comTypeDesc.GetItem = getItem; _comTypeDesc.SetItem = setItem; } }