public SignatureInfoMatchTarget(TypeInfo interfaceTypeInfo, int functionIndex,
            ElemDesc elemDesc, int parameterIndex)
        {
            if (interfaceTypeInfo == null) throw new ArgumentNullException(nameof(interfaceTypeInfo));
            m_interfaceTypeInfo = interfaceTypeInfo;
            m_functionIndex = functionIndex;
            m_funcDesc = interfaceTypeInfo.GetFuncDesc(m_functionIndex);
            m_elemDesc = elemDesc;
            m_parameterIndex = parameterIndex;

            if (m_parameterIndex == 0)
            {
                m_name = "return";
            }
            else
            {
                // the name of the parameter.
                string[] signatureNames = m_interfaceTypeInfo.GetNames(m_funcDesc.memid,
                    m_funcDesc.cParams + 1);
                m_name = signatureNames[m_parameterIndex];
                if (m_name == null || m_name.Trim().Equals(""))
                    m_name = "_unnamed_arg_" + m_parameterIndex;
            }
            // NativeParentFunctionName
            m_nativeParentFunctionName =
                m_interfaceTypeInfo.GetDocumentation(m_funcDesc.memid);

            // NativeSignature
            m_nativeSignature = (new TlbType2String(interfaceTypeInfo, m_elemDesc.tdesc)).GetTypeString();
        }
Exemple #2
0
        public ElemDesc(FuncDesc funcdesc, int index)
        {
            m_parent = funcdesc;
            IntPtr pParam    = funcdesc.m_funcdesc.lprgelemdescParam;
            IntPtr pElemDesc = Utils.MovePointer(pParam, index * Marshal.SizeOf(typeof(ELEMDESC)));

            Init((ELEMDESC)Marshal.PtrToStructure(pElemDesc, typeof(ELEMDESC)));
        }
 public FunctionInfoMatchTarget(TypeInfo parentTypeInfo, int index)
 {
     if (parentTypeInfo == null) throw new ArgumentNullException(nameof(parentTypeInfo));
     m_interfaceTypeInfo = parentTypeInfo;
     m_index = index;
     m_funcDesc = parentTypeInfo.GetFuncDesc(m_index);
     m_nativeParentTypeName = m_interfaceTypeInfo.GetDocumentation();
 }
Exemple #4
0
 public ElemDesc(FuncDesc funcdesc, ELEMDESC elemdesc)
 {
     m_parent = funcdesc;
     Init(elemdesc);
 }
Exemple #5
0
        public ElemDesc(FuncDesc funcdesc, int index)
        {
            if (funcdesc == null) throw new ArgumentNullException(nameof(funcdesc));
            m_parent = funcdesc;
            IntPtr pParam = funcdesc.m_funcdesc.lprgelemdescParam;
            IntPtr pElemDesc = Utils.MovePointer(pParam, index * Marshal.SizeOf(typeof(ELEMDESC)));

            Init( (ELEMDESC) Marshal.PtrToStructure(pElemDesc, typeof(ELEMDESC)));
        }
Exemple #6
0
 public ElemDesc(FuncDesc funcdesc, ELEMDESC elemdesc)
 {
     m_parent = funcdesc;
     Init(elemdesc);
 }
Exemple #7
0
        /// <summary>
        /// Get the return type converter for the function
        /// </summary>
        public static TypeConverter GetReturnType(InterfaceInfo info, InterfaceMemberInfo memInfo,
            FuncDesc func, bool isNewEnumMember, TypeConverter returnConverterOverride,
            List<TypeConverter> parameterConverterOverrideList, out ReturnKind kind,
            out bool isStandardOleCall, out int returnArgId)
        {
            TypeConverter retType = null;
            returnArgId = -1;
            kind = ReturnKind.ReturnValue;
            isStandardOleCall = false;

            TypeDesc retTypeDesc = func.elemdescFunc.tdesc;

            // If /preservesig is specified, we perform the PreserveSig transformation, except for dispatch functions.
            // Because they are not affected by PreserveSig attribute.
            if ((!func.IsDispatch) &&
                (info.ConverterInfo.Settings.m_isPreserveSig ||
                    IsPreserveSigOverride(info, memInfo.Index)))
            {
                if (returnConverterOverride != null)
                {
                    retType = returnConverterOverride;
                    kind = ReturnKind.ReturnValue;
                }
                else if (retTypeDesc.vt == (int)VarEnum.VT_VOID)
                {
                    retType = s_voidTypeConverter;
                    kind = ReturnKind.NoReturn;
                }
                else
                {
                    retType = new TypeConverter(info.ConverterInfo, info.RefTypeInfo, func.elemdescFunc.tdesc, isNewEnumMember, ConversionType.ReturnValue);
                    kind = ReturnKind.ReturnValue;
                }

                return retType;
            }

            // Inspect the return value
            // If the return is HRESULT and PreserveSig switch is not specified, we will do the HRESULT transformation
            // Otherwise, stick to the original return value and use PreserveSigAttribute
            if (retTypeDesc.vt == (int)VarEnum.VT_HRESULT)
            {
                isStandardOleCall = true;
            }
            else
            {
                if (retTypeDesc.vt != (int)VarEnum.VT_VOID && retTypeDesc.vt != (int)VarEnum.VT_HRESULT)
                {
                    if (returnConverterOverride != null)
                        retType = returnConverterOverride;
                    else
                        retType = new TypeConverter(info.ConverterInfo, info.RefTypeInfo,
                            func.elemdescFunc.tdesc, isNewEnumMember, ConversionType.ReturnValue);
                    kind = ReturnKind.ReturnValue;
                }
            }

            if (func.funckind == TypeLibTypes.Interop.FUNCKIND.FUNC_DISPATCH &&
                (!info.ConverterInfo.TransformDispRetVal))
            {
                // Skip RetVal => return value transformation for dispatch interface when TransformDispRetVal is not set
            }
            else
            {
                for (int i = 0; i < func.cParams; ++i)
                {
                    ElemDesc ret = func.GetElemDesc(i);

                    // In a COM type library, the return parameter is logical and is the last parameter
                    // whereas it is an explicit separate item in managed.
                    if (IsRetVal(info.ConverterInfo, ret.paramdesc, func))
                    {
                        // Convert last parameter to return value
                        if (retType == null)
                        {
                            returnArgId = i;
                            if (parameterConverterOverrideList[returnArgId] != null)
                                retType = parameterConverterOverrideList[returnArgId];
                            else
                                retType = new TypeConverter(info.ConverterInfo, info.RefTypeInfo,
                                    ret.tdesc, isNewEnumMember, ConversionType.ParamRetVal);
                            kind = ReturnKind.RetValParameter;
                        }
                        else
                        {
                            info.ConverterInfo.ReportEvent(
                                WarningCode.Wrn_AmbiguousReturn,
                                Resource.FormatString("Wrn_AmbiguousReturn", info.RefTypeInfo.GetDocumentation(), info.RefTypeInfo.GetDocumentation(func.memid)));
                        }
                        break;
                    }
                }
            }

            if (retType == null)
            {
                if (returnConverterOverride != null)
                {
                    retType = returnConverterOverride;
                    kind = ReturnKind.ReturnValue;
                }
                else
                {
                    retType = s_voidTypeConverter;
                    kind = ReturnKind.NoReturn;
                }
            }

            return retType;
        }
Exemple #8
0
        /// <summary>
        /// Check for optional arguments
        /// </summary>
        public static void CheckForOptionalArguments(ConverterInfo info, FuncDesc func, out int varArg, out int firstOptArg, out int lastOptArg)
        {
            int numOfParams = func.cParams;
            varArg = firstOptArg = lastOptArg = numOfParams + 1;

            if (func.cParamsOpt == -1)
            {
                //
                // [vararg] scenario
                //

                // For propput/propputref, the last parameter will be the value to be set
                bool skipPropPutArg = false;
                if ((func.invkind & (TypeLibTypes.Interop.INVOKEKIND.INVOKE_PROPERTYPUT | TypeLibTypes.Interop.INVOKEKIND.INVOKE_PROPERTYPUTREF)) != 0)
                    skipPropPutArg = true;

                // vararg will be the last argument except for lcid arguments & retval arguments
                for (int target = numOfParams - 1; target >= 0; --target)
                {
                    // skip lcid/retval
                    ParamDesc paramDesc = func.GetElemDesc(target).paramdesc;
                    if (IsRetVal(info, paramDesc, func) || paramDesc.IsLCID)
                        continue;

                    // skip for property
                    if (skipPropPutArg)
                    {
                        skipPropPutArg = false;
                        continue;
                    }

                    varArg = target;
                    break;
                }

                Debug.Assert(varArg < numOfParams);
            }
            else if (func.cParamsOpt > 0)
            {
                //
                // [optional] scenario
                //
                int countOfOptionals = func.cParamsOpt;
                firstOptArg = 0;

                // find the first optional arg
                for (int target = func.cParams - 1; target >= 0; --target)
                {
                    // The count of optional params does not include any lcid params, nor does
                    // it include the return value, so skip those.
                    ParamDesc param = func.GetElemDesc(target).paramdesc;
                    if (!(param.IsRetval || param.IsRetval))
                    {
                        if (--countOfOptionals == 0)
                        {
                            firstOptArg = target;
                            break;
                        }
                    }
                }

                lastOptArg = firstOptArg + func.cParamsOpt;
            }
        }
Exemple #9
0
 public static void CreateMethodForDelegate(InterfaceInfo info, FuncDesc funcDesc, int index)
 {
     InterfaceMemberInfo memberInfo = new InterfaceMemberInfo(info.ConverterInfo, info.RefTypeInfo, index, INVOKE_METHOD, INVOKE_METHOD, InterfaceMemberType.Method, TypeLibTypes.Interop.INVOKEKIND.INVOKE_FUNC, funcDesc.memid, funcDesc, null);
     CreateMethod(info, memberInfo, CreateMethodMode.EventDelegateMode);
 }
Exemple #10
0
        /// <summary>
        /// Figure out types for parameters and return a parameter array
        /// </summary>
        /// <returns>TypeConverter[] array for all parameters</returns>
        public static TypeConverter[] GenerateParameterTypes(InterfaceInfo info,
            InterfaceMemberInfo memInfo, FuncDesc func, bool isNewEnumMember,
            int vararg, out int lcidArg, out bool isStandardOleCall,
            out TypeConverter retTypeConverter, out ReturnKind kind, out int retArgId)
        {
            //
            // Check Lcid Parameter
            //
            lcidArg = -1;
            for (int i = 0; i < func.cParams; ++i)
            {
                if (func.GetElemDesc(i).paramdesc.IsLCID)
                {
                    if (lcidArg >= 0)
                    {
                        info.ConverterInfo.ReportEvent(
                            WarningCode.Wrn_MultipleLcids,
                            Resource.FormatString("Wrn_MultipleLcids",
                                info.RefTypeInfo.GetDocumentation(),
                                info.RefTypeInfo.GetDocumentation(func.memid)));
                    }

                    lcidArg = i;
                }
            }

            // Pre-process for the rule engine
            // For return value
            TypeConverter convertToReturnConverter = null;
            GetRuledReturnTypeConverter(info, memInfo, func, out convertToReturnConverter);

            // For parameters
            List<TypeConverter> convertToParameterConverterList;
            GetRuledParameterTypeConverters(info, memInfo, func, out convertToParameterConverterList);

            retTypeConverter = GetReturnType(info, memInfo, func, isNewEnumMember, convertToReturnConverter,
                convertToParameterConverterList, out kind, out isStandardOleCall, out retArgId);

            if ((retTypeConverter == convertToReturnConverter ||
                    convertToParameterConverterList.Contains(retTypeConverter)))
            {
                // From convertTo Action.
                if ((retTypeConverter.ParameterAttributesOverride & ParameterAttributes.In) !=
                    ParameterAttributes.None)
                {
                    Output.WriteWarning(Resource.FormatString("Wrn_ConvertReturnValueToNoneOut",
                                                              info.RefTypeInfo.GetDocumentation(func.memid)),
                                WarningCode.Wrn_ConvertReturnValueToNoneOut);
                }
                retTypeConverter.ParameterAttributesOverride = ParameterAttributes.None;
            }

            int cParams = func.cParams;
            var typeConverterList = new List<TypeConverter>();
            short n;
            for (n = 0; n < cParams; ++n)
            {
                ElemDesc elem = func.GetElemDesc(n);
                ParamDesc paramDesc = elem.paramdesc;

                // Skip LCID
                if (paramDesc.IsLCID)
                    continue;

                // Skip return parameter
                if (kind == ReturnKind.RetValParameter && n == retArgId)
                    continue;

                try
                {
                    ConversionType conversionType;
                    if (n == vararg)
                        conversionType = ConversionType.VarArgParameter;
                    else
                        conversionType = ConversionType.Parameter;

                    if (convertToParameterConverterList[n] != null)
                    {
                        typeConverterList.Add(convertToParameterConverterList[n]);
                    }
                    else
                    {
                        typeConverterList.Add(new TypeConverter(
                            info.ConverterInfo, info.RefTypeInfo, elem.tdesc,
                            paramDesc, false, conversionType));
                    }
                }
                catch (COMException ex)
                {
                    if ((uint)ex.ErrorCode == HResults.TYPE_E_CANTLOADLIBRARY)
                    {
                        string[] names = info.RefTypeInfo.GetNames(func.memid, func.cParams + 1);
                        string name = names[n + 1];

                        if (name != String.Empty)
                        {
                            string msg = Resource.FormatString("Wrn_ParamErrorNamed",
                                new object[] { info.RefTypeInfo.GetDocumentation(), name,
                                    memInfo.UniqueName });
                            info.ConverterInfo.ReportEvent(WarningCode.Wrn_ParamErrorNamed, msg);
                        }
                        else
                        {
                            string msg = Resource.FormatString("Wrn_ParamErrorUnnamed",
                                new object[] { info.RefTypeInfo.GetDocumentation(), n, memInfo.UniqueName });
                            info.ConverterInfo.ReportEvent(WarningCode.Wrn_ParamErrorUnnamed, msg);
                        }
                    }

                    throw;
                }
            }

            return typeConverterList.ToArray();
        }
Exemple #11
0
        private static bool IsRetVal(ConverterInfo info, ParamDesc paramDesc, FuncDesc funcDesc)
        {
            if (paramDesc.IsRetval)
            {
                // Don't consider it is a RetVal for dispatch functions unless TransformDispRetVal is true
                if (funcDesc.funckind == TypeLibTypes.Interop.FUNCKIND.FUNC_DISPATCH && !info.TransformDispRetVal)
                    return false;

                return true;
            }

            return false;
        }
Exemple #12
0
 private static void GetRuledReturnTypeConverter(InterfaceInfo info,
     InterfaceMemberInfo memInfo, FuncDesc func, out TypeConverter convertToReturnConverter)
 {
     convertToReturnConverter = null;
     Rule convertToRule = null;
     if (memInfo.Index != -1)
     {
         // Is not event delegate.
         SignatureInfoMatchTarget returnTarget = new SignatureInfoMatchTarget(
                     info.RefTypeInfo, memInfo.Index, func.elemdescFunc, 0);
         if (info.ConverterInfo.Settings.m_ruleSet != null)
         {
             ICategory signatureCategory = SignatureCategory.GetInstance();
             AbstractActionManager actionManager = RuleEngine.GetActionManager();
             List<Rule> convertToRules = info.ConverterInfo.Settings.m_ruleSet.GetRule(
                 signatureCategory, ConvertToActionDef.GetInstance(), returnTarget);
             if (convertToRules.Count != 0)
             {
                 if (convertToRules.Count > 1)
                 {
                     Output.WriteWarning(
                         Resource.FormatString("Wrn_RuleMultipleMatch",
                                               ConvertToActionDef.GetInstance().GetActionName()),
                         WarningCode.Wrn_RuleMultipleMatch);
                 }
                 convertToRule = convertToRules[convertToRules.Count - 1];
             }
         }
         if (convertToRule != null)
         {
             var convertToAction = convertToRule.Action as ConvertToAction;
             Type typeReturn;
             CustomAttributeBuilder customAttribute;
             ParameterAttributes fixedParameterAttributes;
             GetTypeFromConvertToAction(returnTarget, convertToAction, info.ConverterInfo,
                 info.RefTypeInfo, func.elemdescFunc.tdesc, out typeReturn, out customAttribute,
                 out fixedParameterAttributes);
             convertToReturnConverter =
                 new TypeConverter(typeReturn, customAttribute, fixedParameterAttributes);
         }
     }
 }
Exemple #13
0
        private static void GetRuledParameterTypeConverters(InterfaceInfo info, InterfaceMemberInfo memInfo,
            FuncDesc func, out List<TypeConverter> convertToParameterConverterList)
        {
            int cParams = func.cParams;
            convertToParameterConverterList = new List<TypeConverter>();

            short n;
            for (n = 0; n < cParams; ++n)
            {
                ElemDesc elem = func.GetElemDesc(n);
                ParamDesc paramDesc = elem.paramdesc;

                // "ConvertTo" for basic types and array
                // Rule Engine
                Rule convertToRule = null;
                if (memInfo.Index != -1)
                {
                    // Is not event delegate.
                    SignatureInfoMatchTarget target = new SignatureInfoMatchTarget(
                            info.RefTypeInfo, memInfo.Index, elem, n + 1);
                    if (info.ConverterInfo.Settings.m_ruleSet != null)
                    {
                        ICategory signatureCategory = SignatureCategory.GetInstance();
                        AbstractActionManager actionManager = RuleEngine.GetActionManager();
                        List<Rule> convertToRules = info.ConverterInfo.Settings.m_ruleSet.GetRule(
                            signatureCategory, ConvertToActionDef.GetInstance(), target);
                        if (convertToRules.Count != 0)
                        {
                            if (convertToRules.Count > 1)
                            {
                                Output.WriteWarning(
                                    Resource.FormatString("Wrn_RuleMultipleMatch",
                                                          ConvertToActionDef.GetInstance().GetActionName()),
                                    WarningCode.Wrn_RuleMultipleMatch);
                            }
                            convertToRule = convertToRules[convertToRules.Count - 1];
                        }
                    }
                    if (convertToRule != null)
                    {
                        var convertToAction = convertToRule.Action as ConvertToAction;
                        Type typeReturn;
                        CustomAttributeBuilder customAttribute;
                        ParameterAttributes fixedParameterAttributes;
                        GetTypeFromConvertToAction(target, convertToAction, info.ConverterInfo,
                            info.RefTypeInfo, elem.tdesc, out typeReturn, out customAttribute,
                            out fixedParameterAttributes);
                        convertToParameterConverterList.Add(
                            new TypeConverter(typeReturn, customAttribute, fixedParameterAttributes));
                    }
                    else
                    {
                        convertToParameterConverterList.Add(null);
                    }
                }
                else
                {
                    convertToParameterConverterList.Add(null);
                }
            }
        }
Exemple #14
0
        private static MethodBuilder CreateMethodInternal(InterfaceInfo info, FuncDesc func, InterfaceMemberInfo memberInfo, CreateMethodMode mode, ref bool isConversionLoss)
        {
            bool isNewEnumMember = false;

            if (info.AllowNewEnum && IsNewEnumFunc(info.ConverterInfo, info.RefTypeInfo, func, memberInfo.Index))
            {
                info.AllowNewEnum = false;
                isNewEnumMember = true;

                if (mode == CreateMethodMode.EventDelegateMode)
                {
                    info.ConverterInfo.ReportEvent(
                        WarningCode.Wrn_EventWithNewEnum,
                        Resource.FormatString("Wrn_EventWithNewEnum", info.RefTypeInfo.GetDocumentation()));
                }
            }

            //
            // Optional Arguments
            //
            int varArg;             // index of the vararg argument
            int firstOptArg;        // index of the first optional argument
            int lastOptArg;         // index of the last optional argument
            CheckForOptionalArguments(info.ConverterInfo, func, out varArg, out firstOptArg, out lastOptArg);

            //
            // Figure out types
            //
            ReturnKind returnKind;
            TypeConverter retTypeConverter;
            Type retType;
            bool isStandardOleCall;
            int lcidArg;
            int retArgId;
            TypeConverter[] paramTypeConverters = GenerateParameterTypes(info, memberInfo, func, isNewEnumMember, varArg, out lcidArg, out isStandardOleCall, out retTypeConverter, out returnKind, out retArgId);

            var paramTypes = new Type[paramTypeConverters.Length];
            for (int i = 0; i < paramTypeConverters.Length; ++i)
                paramTypes[i] = paramTypeConverters[i].ConvertedType;

            if (retTypeConverter != null)
                retType = retTypeConverter.ConvertedType;
            else
                retType = null;

            MethodBuilder methodBuilder = CreateMethodCore(info, memberInfo, isNewEnumMember, mode, isStandardOleCall, retType, paramTypes);

            //
            // Emit LCIDConversionAttribute
            //
            if (lcidArg >= 0)
                methodBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForLCIDConversion(lcidArg));

            int cParams = func.cParams;
            int cParamsIter = cParams;

            // If there is a return value, skip the last param
            if (returnKind == ReturnKind.RetValParameter)
            {
                ProcessParam(info, memberInfo, func.GetElemDesc(retArgId), retTypeConverter, methodBuilder, 0, "", false, false);

                isConversionLoss |= retTypeConverter.IsConversionLoss;
            }
            else if (returnKind == ReturnKind.ReturnValue)
            {
                ProcessParam(info, memberInfo, func.elemdescFunc, retTypeConverter, methodBuilder, 0, "", false, false);

                isConversionLoss |= retTypeConverter.IsConversionLoss;
            }

            // First string is the method name so offset by one
            String[] saNames = info.RefTypeInfo.GetNames(func.memid, cParams + 1);

            //
            // Process parameters
            //
            int paramIndex = 0;
            for (int n = 0; n < cParamsIter; ++n)
            {
                ElemDesc elem = func.GetElemDesc(n);

                // Skip LCID
                if (elem.paramdesc.IsLCID)
                    continue;

                // Skip the return parameter
                if (returnKind == ReturnKind.RetValParameter && n == retArgId)
                    continue;

                bool isOptionalArg = (n >= firstOptArg && n <= lastOptArg);
                bool isVarArg = (n == varArg);

                ProcessParam(info, memberInfo, elem, paramTypeConverters[paramIndex], methodBuilder, paramIndex + 1, saNames[n + 1], isVarArg, isOptionalArg);

                isConversionLoss |= paramTypeConverters[paramIndex].IsConversionLoss;
                paramIndex++;
            }

            //
            // Emit TypeLibFuncAttribute if necessary
            //
            if (func.wFuncFlags != 0)
                methodBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForTypeLibFunc((TypeLibFuncFlags)func.wFuncFlags));

            //
            // Handle DefaultMemberAttribute
            //
            if (!memberInfo.IsProperty && memberInfo.DispId == WellKnownDispId.DISPID_VALUE)
            {
                // DIFF: TlbImpv1 use the type library name while we use the unique name
                info.ConverterInfo.SetDefaultMember(info.TypeBuilder, methodBuilder.Name);
            }

            return methodBuilder;
        }
Exemple #15
0
        /// <summary>
        /// Is this function a NewEnum function with the right parameters and DISPID?
        /// </summary>
        public static bool IsNewEnumFunc(ConverterInfo info, TypeInfo typeInfo, FuncDesc func, int index)
        {
            //
            // Support GUID_DispIdOverride
            //
            int dispid = func.memid;
            GetOverrideDispId(info, typeInfo, index, InterfaceMemberType.Method, ref dispid, false);

            if (dispid == WellKnownDispId.DISPID_NEWENUM)
            {
                TypeDesc typeDesc = null;

                if (func.funckind == TypeLibTypes.Interop.FUNCKIND.FUNC_DISPATCH)
                {
                    if (func.IsPropertyGet || func.IsFunc)
                    {
                        if (func.cParams == 0)
                        {
                            typeDesc = func.elemdescFunc.tdesc;
                        }
                        else if (info.TransformDispRetVal && func.cParams == 1 && func.GetElemDesc(0).paramdesc.IsRetval)
                        {
                            typeDesc = func.GetElemDesc(0).tdesc.lptdesc;
                        }
                    }
                }
                else if (func.funckind == TypeLibTypes.Interop.FUNCKIND.FUNC_PUREVIRTUAL)
                {
                    if ((func.cParams == 1) &&
                       (func.IsPropertyGet || func.IsFunc) &&
                       (func.GetElemDesc(0).paramdesc.IsRetval) &&
                       (func.GetElemDesc(0).tdesc.vt == (int)VarEnum.VT_PTR))
                    {
                        typeDesc = func.GetElemDesc(0).tdesc.lptdesc;
                    }
                }

                if (typeDesc != null)
                {
                    if (typeDesc.vt == (int)VarEnum.VT_UNKNOWN || typeDesc.vt == (int)VarEnum.VT_DISPATCH)
                    {
                        // The member returns an IUnknown* or an IDispatch* which is valid.
                        return true;
                    }
                    else if (typeDesc.vt == (int)VarEnum.VT_PTR)
                    {
                        typeDesc = typeDesc.lptdesc;
                        if (typeDesc.vt == (int)VarEnum.VT_USERDEFINED)
                        {
                            TypeInfo type = typeInfo.GetRefTypeInfo(typeDesc.hreftype);
                            using (TypeAttr attr = type.GetTypeAttr())
                            {
                                if (attr.Guid == WellKnownGuids.IID_IUnknown ||
                                   attr.Guid == WellKnownGuids.IID_IDispatch ||
                                   attr.Guid == WellKnownGuids.IID_IEnumVARIANT)
                                {
                                    return true;
                                }
                            }
                        }
                    }
                }
            }

            return false;
        }