Beispiel #1
0
        /// <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);
                    }
                }
            }
        }
Beispiel #4
0
        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);
            }
        }
Beispiel #5
0
        /// <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);
                    }
                }
            }
        }
Beispiel #6
0
        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
        }
Beispiel #7
0
        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());
            }
        }
Beispiel #8
0
        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;
            }
        }
Beispiel #9
0
        /// <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);
            }
        }
Beispiel #10
0
 private void InitTypeAttr()
 {
     TYPEATTR* typeAttr = null;
     try
     {
         typeInfo.GetTypeAttr(out typeAttr);
         this.typeAttr = *typeAttr;
     }
     finally
     {
         if (typeAttr != null)
             typeInfo.ReleaseTypeAttr(typeAttr);
     }
 }
Beispiel #11
0
        /// <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);
            }
        }
Beispiel #12
0
 protected ComType(ITypeLib typeLib, TYPEATTR attrib, int index)
     : base(typeLib, index)
 {
     Index = index;
     SetFlagsFromTypeAttr(attrib);
 }
Beispiel #13
0
 protected ComType(ITypeInfo info, TYPEATTR attrib)
     : base(info)
 {
     SetFlagsFromTypeAttr(attrib);
 }
Beispiel #14
0
 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);
 }
Beispiel #15
0
 public TypeAttr(ITypeInfo typeinfo)
 {
     m_typeInfo = typeinfo;
     m_ipTypeAttr = TypeLibResourceManager.GetDaemon().GetTypeAttr(typeinfo);
     m_typeAttr = (TYPEATTR)Marshal.PtrToStructure(m_ipTypeAttr, typeof(TYPEATTR));
 }