/// <summary> /// Helper method for retrieving type attributes for a given type info /// </summary> /// <param name="typeInfo"></param> /// <param name="typeAttr"></param> /// <returns></returns> internal static void GetTypeAttrForTypeInfo(ITypeInfo typeInfo, out TYPEATTR typeAttr) { IntPtr pAttrs = IntPtr.Zero; typeInfo.GetTypeAttr(out pAttrs); // GetTypeAttr should never return null, this is just to be safe if (pAttrs == IntPtr.Zero) { throw new COMException( ResourceUtilities.FormatResourceString("ResolveComReference.CannotRetrieveTypeInformation")); } try { typeAttr = (TYPEATTR)Marshal.PtrToStructure(pAttrs, typeof(TYPEATTR)); } finally { typeInfo.ReleaseTypeAttr(pAttrs); } }
/// <summary> /// Returns true if we don't need to analyze this particular type. /// </summary> private static bool CanSkipType(ITypeInfo typeInfo, ITypeLib typeLib, TYPEATTR typeAttributes, TYPELIBATTR typeLibAttributes) { // Well known OLE type? if ((typeAttributes.guid == NativeMethods.IID_IUnknown) || (typeAttributes.guid == NativeMethods.IID_IDispatch) || (typeAttributes.guid == NativeMethods.IID_IDispatchEx) || (typeAttributes.guid == NativeMethods.IID_IEnumVariant) || (typeAttributes.guid == NativeMethods.IID_ITypeInfo)) { return(true); } // Is this the Guid type? If so we should be using the corresponding .NET type. if (typeLibAttributes.guid == NativeMethods.IID_StdOle) { typeInfo.GetDocumentation(-1, out string typeName, out _, out _, out _); if (string.CompareOrdinal(typeName, "GUID") == 0) { return(true); } } // Skip types exported from .NET assemblies if (typeLib is ITypeLib2 typeLib2) { typeLib2.GetCustData(ref NativeMethods.GUID_ExportedFromComPlus, out object exportedFromComPlusObj); string exportedFromComPlus = exportedFromComPlusObj as string; if (!string.IsNullOrEmpty(exportedFromComPlus)) { return(true); } } return(false); }
/// <summary> /// For a given type, analyze recursively all the types implemented by it. /// </summary> private void ScanImplementedTypes(ITypeInfo typeInfo, TYPEATTR typeAttributes) { for (int implTypeIndex = 0; implTypeIndex < typeAttributes.cImplTypes; implTypeIndex++) { IFixedTypeInfo implementedType = null; try { var fixedTypeInfo = (IFixedTypeInfo)typeInfo; fixedTypeInfo.GetRefTypeOfImplType(implTypeIndex, out IntPtr hRef); fixedTypeInfo.GetRefTypeInfo(hRef, out implementedType); AnalyzeTypeInfo((ITypeInfo)implementedType); } finally { if (implementedType != null) { _marshalReleaseComObject(implementedType); } } } }
static void DealWithTypeInfo(UCOMITypeInfo it) { // Get the names from ITypeInfo string name; string docstring; Int32 ctxt; string helpfile; // TypeInfo name it.GetDocumentation(-1, out name, out docstring, out ctxt, out helpfile); IntPtr pa; it.GetTypeAttr(out pa); TYPEATTR ta = (TYPEATTR)Marshal.PtrToStructure(pa, typeof(TYPEATTR)); DealWithName(name, ta.guid); // Deal with funcs for (int i = 0; i < ta.cFuncs; i++) { IntPtr pfd; it.GetFuncDesc(i, out pfd); FUNCDESC fd = (FUNCDESC)Marshal.PtrToStructure(pfd, typeof(FUNCDESC)); it.GetDocumentation(fd.memid, out name, out docstring, out ctxt, out helpfile); DealWithName(name, Guid.Empty); } // Deal with vars for (int i = 0; i < ta.cVars; i++) { IntPtr pvd; it.GetVarDesc(i, out pvd); VARDESC vd = (VARDESC)Marshal.PtrToStructure(pvd, typeof(VARDESC)); it.GetDocumentation(vd.memid, out name, out docstring, out ctxt, out helpfile); DealWithName(name, Guid.Empty); } }
/// <summary> /// For a given type, analyze all the functions implemented by it. That means all the argument and return types. /// </summary> /// <param name="typeInfo"></param> /// <param name="typeAttributes"></param> private void ScanDefinedFunctions(ITypeInfo typeInfo, TYPEATTR typeAttributes) { for (int definedFuncIndex = 0; definedFuncIndex < typeAttributes.cFuncs; definedFuncIndex++) { IntPtr funcDescHandleToRelease = IntPtr.Zero; try { FUNCDESC funcDesc; ComReference.GetFuncDescForDescIndex(typeInfo, definedFuncIndex, out funcDesc, out funcDescHandleToRelease); int offset = 0; // Analyze the argument types for (int paramIndex = 0; paramIndex < funcDesc.cParams; paramIndex++) { ELEMDESC elemDesc = (ELEMDESC)Marshal.PtrToStructure( new IntPtr(funcDesc.lprgelemdescParam.ToInt64() + offset), typeof(ELEMDESC)); AnalyzeElement(typeInfo, elemDesc); offset += Marshal.SizeOf <ELEMDESC>(); } // Analyze the return value type AnalyzeElement(typeInfo, funcDesc.elemdescFunc); } finally { if (funcDescHandleToRelease != IntPtr.Zero) { typeInfo.ReleaseFuncDesc(funcDescHandleToRelease); } } } }
public ComImporter(string path, OutputMessageCollection outputMessages, string outputDisplayName) { _outputMessages = outputMessages; _outputDisplayName = outputDisplayName; if (NativeMethods.SfcIsFileProtected(IntPtr.Zero, path) != 0) { outputMessages.AddWarningMessage("GenerateManifest.ComImport", outputDisplayName, _resources.GetString("ComImporter.ProtectedFile")); } object obj = null; try { NativeMethods.LoadTypeLibEx(path, NativeMethods.RegKind.RegKind_None, out obj); } catch (COMException) { } #pragma warning disable 618 UCOMITypeLib tlib = (UCOMITypeLib)obj; if (tlib != null) { IntPtr typeLibAttrPtr = IntPtr.Zero; tlib.GetLibAttr(out typeLibAttrPtr); TYPELIBATTR typeLibAttr = (TYPELIBATTR)Marshal.PtrToStructure(typeLibAttrPtr, typeof(TYPELIBATTR)); tlib.ReleaseTLibAttr(typeLibAttrPtr); Guid tlbid = typeLibAttr.guid; string name, docString, helpFile; int helpContext; tlib.GetDocumentation(-1, out name, out docString, out helpContext, out helpFile); string helpdir = Util.FilterNonprintableChars(helpFile); //Path.GetDirectoryName(helpFile); _typeLib = new TypeLib(tlbid, new Version(typeLibAttr.wMajorVerNum, typeLibAttr.wMinorVerNum), helpdir, typeLibAttr.lcid, Convert.ToInt32(typeLibAttr.wLibFlags, CultureInfo.InvariantCulture)); List <ComClass> comClassList = new List <ComClass>(); int count = tlib.GetTypeInfoCount(); for (int i = 0; i < count; ++i) { TYPEKIND tkind; tlib.GetTypeInfoType(i, out tkind); if (tkind == TYPEKIND.TKIND_COCLASS) { UCOMITypeInfo tinfo; tlib.GetTypeInfo(i, out tinfo); IntPtr tinfoAttrPtr = IntPtr.Zero; tinfo.GetTypeAttr(out tinfoAttrPtr); TYPEATTR tinfoAttr = (TYPEATTR)Marshal.PtrToStructure(tinfoAttrPtr, typeof(TYPEATTR)); tinfo.ReleaseTypeAttr(tinfoAttrPtr); Guid clsid = tinfoAttr.guid; string sclsid = clsid.ToString("B"); tlib.GetDocumentation(i, out name, out docString, out helpContext, out helpFile); string description = Util.FilterNonprintableChars(docString); ClassInfo info = GetRegisteredClassInfo(clsid); if (info == null) { continue; } comClassList.Add(new ComClass(tlbid, clsid, info.Progid, info.ThreadingModel, description)); } } if (comClassList.Count > 0) { _comClasses = comClassList.ToArray(); _success = true; } else { outputMessages.AddErrorMessage("GenerateManifest.ComImport", outputDisplayName, _resources.GetString("ComImporter.NoRegisteredClasses")); _success = false; } } else { outputMessages.AddErrorMessage("GenerateManifest.ComImport", outputDisplayName, _resources.GetString("ComImporter.TypeLibraryLoadFailure")); _success = false; } #pragma warning restore 618 }
private void FillListBoxes(UCOMITypeLib itfTypeLib) { // Clear out current contents. lstBoxCoclasses.Items.Clear(); lstBoxInterfaces.Items.Clear(); lstBoxEnums.Items.Clear(); // Get # of COM types in the library. int typeCount = itfTypeLib.GetTypeInfoCount(); lblNumbOfTypes.Text = "Number of COM Types in file: " + typeCount.ToString(); // Switch between COM type. // Dump out the types. for (int typeIndex = 0; typeIndex < typeCount; typeIndex++) { string typeInfoString; UCOMITypeInfo pInfo; // Get TYPEATTR structure set up. TYPEATTR typeAtt = new TYPEATTR(); Type TYPEATTRType = typeAtt.GetType(); int structSize = Marshal.SizeOf(TYPEATTRType); IntPtr ptr = IntPtr.Zero; ptr = Marshal.AllocHGlobal(structSize); // Get next type info. itfTypeLib.GetTypeInfo(typeIndex, out pInfo); pInfo.GetTypeAttr(out ptr); typeAtt = (TYPEATTR)Marshal.PtrToStructure(ptr, TYPEATTRType); // Based on the kind of COM type, print out some information. string typeName, helpFile, docString; int helpID; switch (typeAtt.typekind) { case TYPEKIND.TKIND_COCLASS: // type is a coclass. pInfo.GetDocumentation(-1, out typeName, out docString, out helpID, out helpFile); typeInfoString = "Name: " + typeName + "\tCLSID: {" + typeAtt.guid.ToString() + "}"; lstBoxCoclasses.Items.Add(typeInfoString); break; case TYPEKIND.TKIND_INTERFACE: // type is a interface. case TYPEKIND.TKIND_DISPATCH: pInfo.GetDocumentation(-1, out typeName, out docString, out helpID, out helpFile); typeInfoString = "Name: " + typeName + "\tIID: {" + typeAtt.guid.ToString() + "}"; lstBoxInterfaces.Items.Add(typeInfoString); break; case TYPEKIND.TKIND_ENUM: // type is a enum. pInfo.GetDocumentation(-1, out typeName, out docString, out helpID, out helpFile); typeInfoString = "Name: " + typeName; lstBoxEnums.Items.Add(typeInfoString); break; } Marshal.DestroyStructure(ptr, typeAtt.GetType()); } }
public ComImporter(string path, OutputMessageCollection outputMessages, string outputDisplayName) { this.outputMessages = outputMessages; this.outputDisplayName = outputDisplayName; if (Microsoft.Build.Tasks.Deployment.ManifestUtilities.NativeMethods.SfcIsFileProtected(IntPtr.Zero, path) != 0) { outputMessages.AddWarningMessage("GenerateManifest.ComImport", new string[] { outputDisplayName, this.resources.GetString("ComImporter.ProtectedFile") }); } object typeLib = null; try { Microsoft.Build.Tasks.Deployment.ManifestUtilities.NativeMethods.LoadTypeLibEx(path, Microsoft.Build.Tasks.Deployment.ManifestUtilities.NativeMethods.RegKind.RegKind_None, out typeLib); } catch (COMException) { } UCOMITypeLib lib = (UCOMITypeLib)typeLib; if (lib != null) { string str; string str2; string str3; int num; IntPtr zero = IntPtr.Zero; lib.GetLibAttr(out zero); TYPELIBATTR typelibattr = (TYPELIBATTR)Marshal.PtrToStructure(zero, typeof(TYPELIBATTR)); lib.ReleaseTLibAttr(zero); Guid tlbId = typelibattr.guid; lib.GetDocumentation(-1, out str, out str2, out num, out str3); string helpDirectory = Microsoft.Build.Tasks.Deployment.ManifestUtilities.Util.FilterNonprintableChars(str3); this.typeLib = new Microsoft.Build.Tasks.Deployment.ManifestUtilities.TypeLib(tlbId, new Version(typelibattr.wMajorVerNum, typelibattr.wMinorVerNum), helpDirectory, typelibattr.lcid, Convert.ToInt32(typelibattr.wLibFlags, CultureInfo.InvariantCulture)); List <ComClass> list = new List <ComClass>(); int typeInfoCount = lib.GetTypeInfoCount(); for (int i = 0; i < typeInfoCount; i++) { TYPEKIND typekind; lib.GetTypeInfoType(i, out typekind); if (typekind == TYPEKIND.TKIND_COCLASS) { UCOMITypeInfo info; lib.GetTypeInfo(i, out info); IntPtr ppTypeAttr = IntPtr.Zero; info.GetTypeAttr(out ppTypeAttr); TYPEATTR typeattr = (TYPEATTR)Marshal.PtrToStructure(ppTypeAttr, typeof(TYPEATTR)); info.ReleaseTypeAttr(ppTypeAttr); Guid guid = typeattr.guid; guid.ToString("B"); lib.GetDocumentation(i, out str, out str2, out num, out str3); string description = Microsoft.Build.Tasks.Deployment.ManifestUtilities.Util.FilterNonprintableChars(str2); ClassInfo registeredClassInfo = this.GetRegisteredClassInfo(guid); if (registeredClassInfo != null) { list.Add(new ComClass(tlbId, guid, registeredClassInfo.Progid, registeredClassInfo.ThreadingModel, description)); } } } if (list.Count > 0) { this.comClasses = list.ToArray(); this.success = true; } else { outputMessages.AddErrorMessage("GenerateManifest.ComImport", new string[] { outputDisplayName, this.resources.GetString("ComImporter.NoRegisteredClasses") }); this.success = false; } } else { outputMessages.AddErrorMessage("GenerateManifest.ComImport", new string[] { outputDisplayName, this.resources.GetString("ComImporter.TypeLibraryLoadFailure") }); this.success = false; } }
/// <summary> /// Determines whether the name belongs to a COM property on the given raw COM object. /// </summary> /// <remarks> /// Looks up type information using the COM ITypeInfo interface. /// Caches the result in the object's built-in COM data area so that subsequent queries for the same name are fast. /// </remarks> /// <param name="obj"></param> /// <param name="memberName"></param> /// <returns>false if no type information is available, or for any error condition.</returns> /// internal static bool IsCOMProp(object obj, string memberName) { if (Utils.IsMono) { return(false); } // The memberName can be changed by the call to GetMemberDispID below (U to _ conversion), but we want // to cache the isComProp value for the unmodified member name, so we save it. string unmodifiedMemberName = memberName; object cachedValue = Marshal.GetComObjectData(obj, "NETLinkIsCOMProp" + unmodifiedMemberName); if (cachedValue != null) { return((bool)cachedValue); } else { UCOMIDispatch iDisp; UCOMITypeInfo iTypeInfo; try { iDisp = GetIDispatch(obj); iTypeInfo = GetITypeInfo(obj, iDisp); } catch (Exception) { Marshal.SetComObjectData(obj, "NETLinkIsCOMProp" + unmodifiedMemberName, false); return(false); } // GetMemberDispID() does not throw on failure--it returns -1. int memberDispId = GetMemberDispID(obj, iDisp, ref memberName); if (memberDispId == -1) { Marshal.SetComObjectData(obj, "NETLinkIsCOMProp" + unmodifiedMemberName, false); return(false); } // We have successfully passed GetIDsOfNames() and GetITypeInfo(), so we know that type info is available and that // the name is a member of the dispatch interface. The name may also have been modified to reflect U to _ conversion. // Previous versions of this method acquired an ITypeInfo2 from the ITypeInfo and called GetFuncIndexOfMemId() to get // a function index suitable for GetFuncDesc(). There were problems with that technique, in that the index returned // sometimes (not always) needed to have 7 added to it. Because we cache the T/F result from this method anyway, // we now just exhaustively call GetFuncDesc() on all the members, looking for one with the right memberDispId. // Then we can check its func info to see if it is a property with no args. bool result = false; IntPtr pTypeAttr; iTypeInfo.GetTypeAttr(out pTypeAttr); TYPEATTR typeAttr = (TYPEATTR)Marshal.PtrToStructure(pTypeAttr, typeof(TYPEATTR)); int numFuncs = typeAttr.cFuncs; iTypeInfo.ReleaseTypeAttr(pTypeAttr); for (int i = 0; i < numFuncs; i++) { IntPtr pFuncDesc; iTypeInfo.GetFuncDesc(i, out pFuncDesc); FUNCDESC funcDesc = (FUNCDESC)Marshal.PtrToStructure(pFuncDesc, typeof(FUNCDESC)); int thisMemberID = funcDesc.memid; INVOKEKIND invokeKind = funcDesc.invkind; int numParams = funcDesc.cParams; iTypeInfo.ReleaseFuncDesc(pFuncDesc); if (thisMemberID == memberDispId) { result = invokeKind == INVOKEKIND.INVOKE_PROPERTYGET && numParams == 0; break; } } Marshal.SetComObjectData(obj, "NETLinkIsCOMProp" + unmodifiedMemberName, result); return(result); } }
private void InitTypeAttr() { TYPEATTR* typeAttr = null; try { typeInfo.GetTypeAttr(out typeAttr); this.typeAttr = *typeAttr; } finally { if (typeAttr != null) typeInfo.ReleaseTypeAttr(typeAttr); } }
/// <summary> /// Gets parameter information for the given member. /// </summary> /// <remarks> /// Uses the COM ITypeInfo interface to get the information. Does not throw. If it returns false then the out params /// will not hold useful information. /// </remarks> /// <param name="obj"></param> /// <param name="memberName"></param> /// <param name="callType"></param> /// <param name="isBeingCalledWithZeroArgs"></param> /// <param name="paramTypes"></param> /// <param name="paramFlags"></param> /// <param name="endsWithParamArray"></param> /// <returns>true if the name refers to a valid member or if no type information is available</returns> /// internal static bool GetMemberInfo(object obj, ref string memberName, int callType, bool isBeingCalledWithZeroArgs, out Type[] paramTypes, out PARAMFLAG[] paramFlags, out bool endsWithParamArray) { // There are some early returns in this method, so we initialize the out params right away. To the caller, if these values // come back null it means that the information could not be determined. paramTypes = null; paramFlags = null; endsWithParamArray = false; int defaultLCID = GetUserDefaultLCID(); try { // Throws in this outer try cause true to be returned. They mean "type info could not be obtained, so the member is not // known to be invalid." UCOMIDispatch iDisp = GetIDispatch(obj); int memberDispId = GetMemberDispID(obj, iDisp, ref memberName); if (memberDispId == -1) { // Name not found by GetIDsOfNames. return(false); } // If no args are being passed, then we can skip all the machinations below about type info. if (isBeingCalledWithZeroArgs) { return(true); } UCOMITypeInfo iTypeInfo = GetITypeInfo(obj, iDisp); IntPtr pFuncDesc; // Check to see if the func index for this member name is already cached from a previous call. FuncIndexHolder fih = (FuncIndexHolder)Marshal.GetComObjectData(obj, "NETLinkFuncIndex" + memberName); if (fih == null) { // This will be populated below. fih = new FuncIndexHolder(); Marshal.SetComObjectData(obj, "NETLinkFuncIndex" + memberName, fih); } int funcIndex = -1; if (callType == Install.CALLTYPE_FIELD_OR_SIMPLE_PROP_GET) { if (fih.funcIndexForCALLTYPE_FIELD_OR_SIMPLE_PROP_GET != -1) { funcIndex = fih.funcIndexForCALLTYPE_FIELD_OR_SIMPLE_PROP_GET; } } else if (callType == Install.CALLTYPE_FIELD_OR_SIMPLE_PROP_SET || callType == Install.CALLTYPE_PARAM_PROP_SET) { if (fih.funcIndexForCALLTYPE_FIELD_OR_ANY_PROP_SET != -1) { funcIndex = fih.funcIndexForCALLTYPE_FIELD_OR_ANY_PROP_SET; } } else if (callType == Install.CALLTYPE_METHOD || callType == Install.CALLTYPE_PARAM_PROP_GET) { // COM objects are treated by M code as if they all have indexers, so calls like obj[1] will // come in as CALLTYPE_PARAM_PROP_GET with a property name of Item. We can just treat these like // method calls. if (fih.funcIndexForCALLTYPE_METHOD != -1) { funcIndex = fih.funcIndexForCALLTYPE_METHOD; } } // Did not have the func index for this call type cached. if (funcIndex == -1) { IntPtr pTypeAttr; iTypeInfo.GetTypeAttr(out pTypeAttr); TYPEATTR typeAttr = (TYPEATTR)Marshal.PtrToStructure(pTypeAttr, typeof(TYPEATTR)); int numFuncs = typeAttr.cFuncs; iTypeInfo.ReleaseTypeAttr(pTypeAttr); bool foundDispId = false; for (int thisIndex = 0; thisIndex < numFuncs; thisIndex++) { // Be aware that GetFuncDesc() can (I think) throw a cryptic "Element not found" exception, // such as for a hidden property like (Excel) _Application.ActiveDialog. iTypeInfo.GetFuncDesc(thisIndex, out pFuncDesc); FUNCDESC funcDesc = (FUNCDESC)Marshal.PtrToStructure(pFuncDesc, typeof(FUNCDESC)); int thisMemberId = funcDesc.memid; INVOKEKIND invokeKind = funcDesc.invkind; iTypeInfo.ReleaseFuncDesc(pFuncDesc); if (thisMemberId == memberDispId) { foundDispId = true; // Verify that it is a member of the correct call type. if (callType == Install.CALLTYPE_FIELD_OR_SIMPLE_PROP_GET && invokeKind == INVOKEKIND.INVOKE_PROPERTYGET) { fih.funcIndexForCALLTYPE_FIELD_OR_SIMPLE_PROP_GET = thisIndex; funcIndex = thisIndex; break; } else if ((callType == Install.CALLTYPE_FIELD_OR_SIMPLE_PROP_SET || callType == Install.CALLTYPE_PARAM_PROP_SET) && (invokeKind == INVOKEKIND.INVOKE_PROPERTYPUT || invokeKind == INVOKEKIND.INVOKE_PROPERTYPUTREF)) { fih.funcIndexForCALLTYPE_FIELD_OR_ANY_PROP_SET = thisIndex; funcIndex = thisIndex; break; } else if ((callType == Install.CALLTYPE_METHOD && (invokeKind == INVOKEKIND.INVOKE_FUNC || invokeKind == INVOKEKIND.INVOKE_PROPERTYGET)) || (callType == Install.CALLTYPE_PARAM_PROP_GET && invokeKind == INVOKEKIND.INVOKE_PROPERTYGET)) { // Parameterized prop gets, not sets, look like CALLTYPE_METHOD. Also, as discussed in an earlier comment, // indexer notation calls (obj[1]) are supported for all COM objects and come in as CALLTYPE_PARAM_PROP_GET. fih.funcIndexForCALLTYPE_METHOD = thisIndex; funcIndex = thisIndex; break; } } } if (funcIndex == -1) { // We didn't find the member in our search. This can happen in two ways. First, the member might // exist but not be the right call type. For this case we want to return false. Second, we didn't // even find the dispid. This can happen in unusual cases I don't understan An example of this // is the IWebBrowser2 interface obtained by CreateCOMObject["InternetExplorer.Application"]. // For this case we want to return true, as if there was no type info at all available, so the // call can still proceed. return(!foundDispId); } } // If we get to here, we have a valid funcIndex and memberDispId, and the member is of the correct variety // that corresponds to how it was called (e.g., it's a method and it was called as such). All that // remains is to get the parameter types. iTypeInfo.GetFuncDesc(funcIndex, out pFuncDesc); try { FUNCDESC funcDesc = (FUNCDESC)Marshal.PtrToStructure(pFuncDesc, typeof(FUNCDESC)); Debug.Assert(funcDesc.memid == memberDispId); int paramCount = funcDesc.cParams; // Functions that end with a VB-style ParamArray (a variable-length argument sequence) have -1 for the // cParamsOpt member. It is convenient to treat them specially, hence the 'endsWithParamArray' variable // (which is an out param for this method). The special treatment involves leaving the ParamArray arg off // the list of paramFlags and paramTypes. We just pretend there is one less arg to the function but // record that it ends with a ParamArray. We always know the type of this arg anyway: ByRef Variant[]. // To the caller, though, the individual args are sent as a sequence, not packed into an array. endsWithParamArray = funcDesc.cParamsOpt == -1; if (endsWithParamArray) { paramCount--; } paramTypes = new Type[paramCount]; paramFlags = new PARAMFLAG[paramCount]; IntPtr pElemDescArray = funcDesc.lprgelemdescParam; for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) { ELEMDESC elemDesc = (ELEMDESC)Marshal.PtrToStructure((IntPtr)(pElemDescArray.ToInt64() + paramIndex * Marshal.SizeOf(typeof(ELEMDESC))), typeof(ELEMDESC)); TYPEDESC typeDesc = elemDesc.tdesc; paramFlags[paramIndex] = elemDesc.desc.paramdesc.wParamFlags; // I think I should never see a retval param here. They have been automatically converted to return types. Debug.Assert((paramFlags[paramIndex] & PARAMFLAG.PARAMFLAG_FRETVAL) == 0); VarEnum variantType = (VarEnum)typeDesc.vt; bool isArray = variantType == VarEnum.VT_SAFEARRAY; bool isPtr = variantType == VarEnum.VT_PTR; bool isOut = (paramFlags[paramIndex] & PARAMFLAG.PARAMFLAG_FOUT) != 0; // VB array params will have isPtr and !isArray, because they are always ByRef (thus ptrs). // In general (always?), out params will be VT_PTR. if (isArray || isPtr) { IntPtr pElementTypeDesc = typeDesc.lpValue; TYPEDESC elementTypeDesc = (TYPEDESC)Marshal.PtrToStructure(pElementTypeDesc, typeof(TYPEDESC)); variantType = (VarEnum)elementTypeDesc.vt; // If the arg was a ptr to an array (e.g., as in VB objects), do it again to get the element type. if (variantType == VarEnum.VT_SAFEARRAY) { isArray = true; pElementTypeDesc = elementTypeDesc.lpValue; elementTypeDesc = (TYPEDESC)Marshal.PtrToStructure(pElementTypeDesc, typeof(TYPEDESC)); variantType = (VarEnum)elementTypeDesc.vt; } } paramTypes[paramIndex] = managedTypeForVariantType(variantType, isArray, isPtr, isOut); } } finally { iTypeInfo.ReleaseFuncDesc(pFuncDesc); } return(true); } catch (Exception) { return(true); } }
protected ComType(ITypeLib typeLib, TYPEATTR attrib, int index) : base(typeLib, index) { Index = index; SetFlagsFromTypeAttr(attrib); }
protected ComType(ITypeInfo info, TYPEATTR attrib) : base(info) { SetFlagsFromTypeAttr(attrib); }
public unsafe int RemoteGetTypeAttr(TYPEATTR** ppTypeAttr, CLEANLOCALSTORAGE* pDummy) { ITypeInfo_vtbl** @this = (ITypeInfo_vtbl**)reference; ITypeInfo_vtbl* vtbl = *@this; if (vtbl == null) throw new InvalidComObjectException(); Delegate genericDelegate = Marshal.GetDelegateForFunctionPointer(vtbl->method_3, typeof(delegate_3)); delegate_3 method = (delegate_3)genericDelegate; return method(@this, ppTypeAttr, pDummy); }
public TypeAttr(ITypeInfo typeinfo) { m_typeInfo = typeinfo; m_ipTypeAttr = TypeLibResourceManager.GetDaemon().GetTypeAttr(typeinfo); m_typeAttr = (TYPEATTR)Marshal.PtrToStructure(m_ipTypeAttr, typeof(TYPEATTR)); }