Ejemplo n.º 1
0
        internal ComMethodDesc(ITypeInfo typeInfo, FUNCDESC funcDesc)
            : this(funcDesc.memid)
        {
            InvokeKind = funcDesc.invkind;

            int cNames;

            string[] rgNames = new string[1 + funcDesc.cParams];
            typeInfo.GetNames(DispId, rgNames, rgNames.Length, out cNames);

            bool skipLast = false;

            if (IsPropertyPut && rgNames[rgNames.Length - 1] == null)
            {
                rgNames[rgNames.Length - 1] = "value";
                cNames++;
                skipLast = true;
            }
            Debug.Assert(cNames == rgNames.Length);
            _name = rgNames[0];

            ParamCount = funcDesc.cParams;

            ReturnType           = ComUtil.GetTypeFromTypeDesc(funcDesc.elemdescFunc.tdesc);
            ParameterInformation = ComUtil.GetParameterInformation(funcDesc, skipLast);
        }
        protected void AddParams(FUNCDESC funcDesc,
                                 String[] names,
                                 int paramCount)
        {
            IntPtr elemPtr = funcDesc.lprgelemdescParam;

            for (int i = 0; i < paramCount; i++)
            {
                ELEMDESC elemDesc =
                    (ELEMDESC)Marshal.PtrToStructure(elemPtr,
                                                     typeof(ELEMDESC));
                ComParamInfo pi = new ComParamInfo
                                      (names[i + 1],
                                      TypeLibUtil.TYPEDESCToString
                                          (_typeLib,
                                          _typeInfo,
                                          elemDesc.tdesc,
                                          TypeLibUtil.COMTYPE),
                                      elemDesc.desc.paramdesc.wParamFlags);
                _parameters.Add(pi);
                // Point to the next one
                elemPtr = new IntPtr(elemPtr.ToInt64() +
                                     Marshal.SizeOf(elemDesc));
            }
        }
Ejemplo n.º 3
0
        internal ComMethodDesc(ITypeInfo typeInfo, FUNCDESC funcDesc)
            : this(funcDesc.memid)
        {
            _hasTypeInfo = true;
            InvokeKind   = funcDesc.invkind;

            int cNames;

            string[] rgNames = new string[1 + funcDesc.cParams];
            typeInfo.GetNames(_memid, rgNames, rgNames.Length, out cNames);
            if (IsPropertyPut && rgNames[rgNames.Length - 1] == null)
            {
                rgNames[rgNames.Length - 1] = "value";
                cNames++;
            }
            Debug.Assert(cNames == rgNames.Length);
            _name = rgNames[0];

            _parameters = new ComParamDesc[funcDesc.cParams];

            int offset = 0;

            for (int i = 0; i < funcDesc.cParams; i++)
            {
                ELEMDESC elemDesc = (ELEMDESC)Marshal.PtrToStructure(
                    new IntPtr(funcDesc.lprgelemdescParam.ToInt64() + offset),
                    typeof(ELEMDESC));

                _parameters[i] = new ComParamDesc(ref elemDesc, rgNames[1 + i]);

                offset += Marshal.SizeOf(typeof(ELEMDESC));
            }
        }
Ejemplo n.º 4
0
        public void GetFuncDesc(int index, out IntPtr ppFuncDesc)
        {
            // Fail BEFORE allocating the handle to avoid leaks. If the real COM object fails in this method
            // and doesn't return the handle or clean it up itself there's not much we can do to avoid the leak.
            _faultInjector.FailurePointThrow(MockTypeLibrariesFailurePoints.ITypeInfo_GetFuncDesc);

            ppFuncDesc = _memoryHelper.AllocateHandle(Marshal.SizeOf <FUNCDESC>());

            _memoryHelper.EnterSubAllocationScope(ppFuncDesc);
            FUNCDESC funcDesc = new FUNCDESC();

            funcDesc.lprgelemdescParam = _memoryHelper.AllocateHandle(_definedFunctions[index].parameters.Length * Marshal.SizeOf <ELEMDESC>());
            funcDesc.cParams           = (short)_definedFunctions[index].parameters.Length;

            for (int i = 0; i < _definedFunctions[index].parameters.Length; i++)
            {
                ELEMDESC elemDesc = new ELEMDESC();
                elemDesc.tdesc = _definedFunctions[index].parameters[i].CreateTypeDesc(
                    new IntPtr(index * s_HREF_FUNCSPARAM_OFFSET_PERFUNC + i + s_HREF_FUNCSPARAM_OFFSET), _memoryHelper);

                Marshal.StructureToPtr(
                    elemDesc,
                    new IntPtr(funcDesc.lprgelemdescParam.ToInt64() + i * Marshal.SizeOf <ELEMDESC>()),
                    false);
            }

            funcDesc.elemdescFunc.tdesc = _definedFunctions[index].returnType.CreateTypeDesc(
                new IntPtr(index + s_HREF_FUNCSRET_OFFSET), _memoryHelper);
            _memoryHelper.ExitSubAllocationScope();

            Marshal.StructureToPtr(funcDesc, ppFuncDesc, false);
        }
        protected void AddDomParams(FUNCDESC funcDesc,
                                    CodeMemberMethod meth,
                                    int limit)
        {
            IntPtr elemPtr = funcDesc.lprgelemdescParam;

            for (int i = 0; i < limit; i++)
            {
                ELEMDESC elemDesc =
                    (ELEMDESC)Marshal.PtrToStructure(elemPtr,
                                                     typeof(ELEMDESC));
                ComParamInfo parameter = (ComParamInfo)
                                         _parameters[i];
                String paramType = TypeLibUtil.TYPEDESCToString
                                       (_typeLib,
                                       _typeInfo,
                                       elemDesc.tdesc,
                                       !TypeLibUtil.COMTYPE);
                String paramInOut = null;
                if ((parameter._paramFlags & PARAMFLAG.PARAMFLAG_FIN) != 0)
                {
                    paramInOut = "In";
                }
                else if
                ((parameter._paramFlags & PARAMFLAG.PARAMFLAG_FOUT) != 0)
                {
                    paramInOut = "Out";
                    // Ref becomes out for an output parameter
                    if (paramType.StartsWith("ref "))
                    {
                        paramType = "out " + paramType.Substring(4);
                    }
                    else
                    {
                        paramType = "out " + paramType;
                    }
                }
                CodeParameterDeclarationExpression paramExpr =
                    new CodeParameterDeclarationExpression
                        (paramType, parameter._name);
                if (paramInOut != null)
                {
                    paramExpr.CustomAttributes.Add
                        (new CodeAttributeDeclaration
                            ("System.Runtime.InteropServices." + paramInOut));
                }
                meth.Parameters.Add(paramExpr);
                // Point to the next one
                elemPtr = new IntPtr(elemPtr.ToInt64() +
                                     Marshal.SizeOf(elemDesc));
            }
        }
Ejemplo n.º 6
0
        public unsafe MethodDesc(string name, string dll, string entryPoint, FUNCDESC funcdesc, string[] argumentNames, Func<uint, TypeDesc> typeFactory)
        {
            string tmpl = "___overloaded000";
            if ((name.Length > tmpl.Length) && (name.IndexOf("___overloaded") == (name.Length - tmpl.Length)))
                name = name.Substring(0, name.Length - tmpl.Length);

            Name = EscapMethodName(name);
            Dll = dll;
            EntryPoint = entryPoint;

            Offset = funcdesc.oVft;

            ReturnValue = new ParameterDesc(funcdesc.elemdescFunc, string.Empty, typeFactory, 0, false, null);
            List<ParameterDesc> parameters = new List<ParameterDesc>();
            for (int i = 0; i < funcdesc.cParams; i++)
                parameters.Add(new ParameterDesc(funcdesc.lprgelemdescParam[i], (i < argumentNames.Length) ? argumentNames[i] : "__arg" + i, typeFactory, 0, false, null));
            Parameters = parameters.AsReadOnly();

            //if (funcdesc.cParamsOpt != 0)
            //    throw new Exception("Variable number of optional parameters is not supported");
            //if (funcdesc.invkind != INVOKEKIND.INVOKE_FUNC)
            //    throw new Exception("Only functions are currently supported");
            if (funcdesc.cScodes >= 1)
                throw new Exception("Only one return value is supported");

            switch (funcdesc.callconv)
            {
                case System.Runtime.InteropServices.ComTypes.CALLCONV.CC_CDECL:
                    Convention = CallingConvention.Cdecl;
                    break;
                case System.Runtime.InteropServices.ComTypes.CALLCONV.CC_STDCALL:
                    Convention = CallingConvention.StdCall;
                    break;
                default:
                    throw new Exception("Calling convention " + funcdesc.callconv + " is not supported");
            }

            switch (funcdesc.funckind)
            {
                case FUNCKIND.FUNC_DISPATCH:
                case FUNCKIND.FUNC_VIRTUAL:
                case FUNCKIND.FUNC_PUREVIRTUAL:
                case FUNCKIND.FUNC_NONVIRTUAL:
                case FUNCKIND.FUNC_STATIC:
                    break;
                default:
                    throw new Exception("Function kind " + funcdesc.funckind + " is not supported");
            }
        }
Ejemplo n.º 7
0
        internal ComMethodDesc(ITypeInfo typeInfo, FUNCDESC funcDesc)
            : this(funcDesc.memid)
        {
            _invokeKind = funcDesc.invkind;

            string[] rgNames = new string[1 + funcDesc.cParams];
            typeInfo.GetNames(DispId, rgNames, rgNames.Length, out int cNames);
            if (IsPropertyPut && rgNames[rgNames.Length - 1] == null)
            {
                rgNames[rgNames.Length - 1] = "value";
                cNames++;
            }
            Debug.Assert(cNames == rgNames.Length);
            Name = rgNames[0];

            ParamCount = funcDesc.cParams;
        }
Ejemplo n.º 8
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);
            }
        }
        internal ComMemberInfo(BasicInfo parent,
                               TYPEKIND typeKind,
                               UCOMITypeInfo typeInfo,
                               int index,
                               bool dispatch,
                               FUNCDESC funcDesc) :
            base(typeInfo)
        {
            int actLen;

            String[] memberNames = new String[100];
            _typeInfo.GetNames(funcDesc.memid, memberNames,
                               memberNames.Length,
                               out actLen);

            _memberId = funcDesc.memid;
            // the high order part of the memberId is flags
            // for a dispatch interface
            if (dispatch)
            {
                _memberId &= 0xffff;
                // Make sure we get a 16 bit integer so that negative
                // DISPIDs show up correctly
                _memberId = (Int16)_memberId;
            }
            String docString;

            // Note, use the original unmasked memberId
            _typeInfo.GetDocumentation(funcDesc.memid, out _name,
                                       out docString, out _helpContext,
                                       out _helpFile);
            // Set using property so that nulls are checked
            DocString   = docString;
            _parameters = new ArrayList();
            _typeLib    = parent.TypeLib;
            _index      = index;
            _container  = parent;
            _printName  = _name;
            _nameKey    = (String)_name;
            // Add the DISPID to the dispatch interfaces
            if (dispatch)
            {
                _dispatch   = true;
                _printName += " - " + _memberId;
            }
            if (TraceUtil.If(this, TraceLevel.Verbose))
            {
                Trace.WriteLine("MemberInfo: " + _name);
            }
            _type = TypeLibUtil.TYPEDESCToString
                        (_typeLib,
                        _typeInfo,
                        funcDesc.elemdescFunc.tdesc,
                        TypeLibUtil.COMTYPE);
            if (funcDesc.invkind == INVOKEKIND.INVOKE_FUNC)
            {
                _infoType = "Function";
                _property = false;
                if (funcDesc.cParams > 0)
                {
                    AddParams(funcDesc, memberNames, funcDesc.cParams);
                }
            }
            else
            {
                if (funcDesc.invkind == INVOKEKIND.INVOKE_PROPERTYGET)
                {
                    _printName += " (get)";
                    _nameKey   += NAMEKEY_GET;
                }
                else if (funcDesc.invkind == INVOKEKIND.INVOKE_PROPERTYPUT)
                {
                    _printName += " (put)";
                    _nameKey   += NAMEKEY_SET;
                }
                else if (funcDesc.invkind == INVOKEKIND.INVOKE_PROPERTYPUTREF)
                {
                    _printName += " (put ref)";
                    _nameKey   += NAMEKEY_SETREF;
                }
                _infoType = "Property";
                _property = true;
            }
            _flagsString = FlagsString((FUNCFLAGS)funcDesc.wFuncFlags);
            if (_property)
            {
                _presInfo = PresentationMap.
                            GetInfo(PresentationMap.COM_PROPERTY);
            }
            else
            {
                _presInfo = PresentationMap.
                            GetInfo(PresentationMap.COM_METHOD);
            }
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Helper method for retrieving the function description structure for the given function index.
        /// This method needs to also return the native pointer to be released when we're done with our FUNCDESC.
        /// It's not really possible to copy everything to a managed struct and then release the ptr immediately
        /// here, since FUNCDESCs contain other native pointers we may need to access.
        /// </summary>
        internal static void GetFuncDescForDescIndex(ITypeInfo typeInfo, int funcIndex, out FUNCDESC funcDesc, out IntPtr funcDescHandle)
        {
            typeInfo.GetFuncDesc(funcIndex, out IntPtr pFuncDesc);

            // GetFuncDesc should never return null, this is just to be safe
            if (pFuncDesc == IntPtr.Zero)
            {
                throw new COMException(
                          ResourceUtilities.GetResourceString("ResolveComReference.CannotRetrieveTypeInformation"));
            }

            funcDesc       = (FUNCDESC)Marshal.PtrToStructure(pFuncDesc, typeof(FUNCDESC));
            funcDescHandle = pFuncDesc;
        }
Ejemplo n.º 11
0
 public FuncDesc(int index, ITypeInfo typeinfo)
 {
     m_typeinfo = typeinfo;
     m_ipFuncDesc = TypeLibResourceManager.GetDaemon().GetFuncDesc(typeinfo, index);
     m_funcdesc = (FUNCDESC)Marshal.PtrToStructure(m_ipFuncDesc, typeof(FUNCDESC));
 }
Ejemplo n.º 12
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);
            }
        }
Ejemplo n.º 13
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);
            }
        }
Ejemplo n.º 14
0
 public unsafe int RemoteGetFuncDesc(uint index, FUNCDESC** ppFuncDesc, CLEANLOCALSTORAGE* pDummy)
 {
     ITypeInfo_vtbl** @this = (ITypeInfo_vtbl**)reference;
     ITypeInfo_vtbl* vtbl = *@this;
     if (vtbl == null)
         throw new InvalidComObjectException();
     Delegate genericDelegate = Marshal.GetDelegateForFunctionPointer(vtbl->method_5, typeof(delegate_5));
     delegate_5 method = (delegate_5)genericDelegate;
     return method(@this, index, ppFuncDesc, pDummy);
 }
Ejemplo n.º 15
0
 public unsafe int RemoteBind(char* szName, uint lHashVal, ushort wFlags, ITypeInfo* ppTInfo, DESCKIND* pDescKind, FUNCDESC** ppFuncDesc, VARDESC** ppVarDesc, ITypeComp* ppTypeComp, CLEANLOCALSTORAGE* pDummy)
 {
     ITypeComp_vtbl** @this = (ITypeComp_vtbl**)reference;
     ITypeComp_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, szName, lHashVal, wFlags, ppTInfo, pDescKind, ppFuncDesc, ppVarDesc, ppTypeComp, pDummy);
 }