Example #1
0
 internal ComTypeDesc(ITypeInfo typeInfo, ComTypeLibDesc typeLibDesc)
 {
     if (typeInfo != null)
     {
         ComRuntimeHelpers.GetInfoFromType(typeInfo, out _typeName, out _documentation);
     }
     TypeLib = typeLibDesc;
 }
Example #2
0
        internal override Expression MarshalToRef(Expression parameter)
        {
            parameter = Marshal(parameter);

            // parameter == null ? IntPtr.Zero : Marshal.GetIDispatchForObject(parameter);
            return(Expression.Condition(
                       Expression.Equal(parameter, Expression.Constant(null)),
                       Expression.Constant(IntPtr.Zero),
                       Expression.Call(
                           ComRuntimeHelpers.GetGetIDispatchForObjectMethod(),
                           parameter
                           )
                       ));
        }
Example #3
0
        private void AddInterface(ComTypes.ITypeInfo itfTypeInfo, bool isSourceItf)
        {
            string itfName = ComRuntimeHelpers.GetNameOfType(itfTypeInfo);

            if (isSourceItf)
            {
                _sourceItfs ??= new LinkedList <string>();
                _sourceItfs.AddLast(itfName);
            }
            else
            {
                _itfs ??= new LinkedList <string>();
                _itfs.AddLast(itfName);
            }
        }
Example #4
0
        private static void ScanSourceInterface(ComTypes.ITypeInfo sourceTypeInfo, ref Dictionary <string, ComEventDesc> events)
        {
            ComTypes.TYPEATTR sourceTypeAttribute = ComRuntimeHelpers.GetTypeAttrForTypeInfo(sourceTypeInfo);

            for (int index = 0; index < sourceTypeAttribute.cFuncs; index++)
            {
                IntPtr funcDescHandleToRelease = IntPtr.Zero;

                try
                {
                    GetFuncDescForDescIndex(sourceTypeInfo, index, out ComTypes.FUNCDESC funcDesc, out funcDescHandleToRelease);

                    // we are not interested in hidden or restricted functions for now.
                    if ((funcDesc.wFuncFlags & (int)ComTypes.FUNCFLAGS.FUNCFLAG_FHIDDEN) != 0)
                    {
                        continue;
                    }
                    if ((funcDesc.wFuncFlags & (int)ComTypes.FUNCFLAGS.FUNCFLAG_FRESTRICTED) != 0)
                    {
                        continue;
                    }

                    string name = ComRuntimeHelpers.GetNameOfMethod(sourceTypeInfo, funcDesc.memid);
                    name = name.ToUpper(System.Globalization.CultureInfo.InvariantCulture);

                    // Sometimes coclass has multiple source interfaces. Usually this is caused by
                    // adding new events and putting them on new interfaces while keeping the
                    // old interfaces around. This may cause name collisioning which we are
                    // resolving by keeping only the first event with the same name.
                    if (!events.ContainsKey(name))
                    {
                        ComEventDesc eventDesc = new ComEventDesc
                        {
                            Dispid    = funcDesc.memid,
                            SourceIID = sourceTypeAttribute.guid
                        };
                        events.Add(name, eventDesc);
                    }
                }
                finally
                {
                    if (funcDescHandleToRelease != IntPtr.Zero)
                    {
                        sourceTypeInfo.ReleaseFuncDesc(funcDescHandleToRelease);
                    }
                }
            }
        }
Example #5
0
        internal ComTypeClassDesc(ComTypes.ITypeInfo typeInfo, ComTypeLibDesc typeLibDesc) :
            base(typeInfo, typeLibDesc)
        {
            ComTypes.TYPEATTR typeAttr = ComRuntimeHelpers.GetTypeAttrForTypeInfo(typeInfo);
            Guid = typeAttr.guid;

            for (int i = 0; i < typeAttr.cImplTypes; i++)
            {
                typeInfo.GetRefTypeOfImplType(i, out int hRefType);
                typeInfo.GetRefTypeInfo(hRefType, out ComTypes.ITypeInfo currentTypeInfo);
                typeInfo.GetImplTypeFlags(i, out ComTypes.IMPLTYPEFLAGS implTypeFlags);

                bool isSourceItf = (implTypeFlags & ComTypes.IMPLTYPEFLAGS.IMPLTYPEFLAG_FSOURCE) != 0;
                AddInterface(currentTypeInfo, isSourceItf);
            }
        }
Example #6
0
        private static ComTypes.ITypeInfo GetCoClassTypeInfo(object rcw, ComTypes.ITypeInfo typeInfo)
        {
            Debug.Assert(typeInfo != null);

            if (rcw is IProvideClassInfo provideClassInfo)
            {
                IntPtr typeInfoPtr = IntPtr.Zero;
                try
                {
                    provideClassInfo.GetClassInfo(out typeInfoPtr);
                    if (typeInfoPtr != IntPtr.Zero)
                    {
                        return(Marshal.GetObjectForIUnknown(typeInfoPtr) as ComTypes.ITypeInfo);
                    }
                }
                finally
                {
                    if (typeInfoPtr != IntPtr.Zero)
                    {
                        Marshal.Release(typeInfoPtr);
                    }
                }
            }

            // retrieving class information through IPCI has failed -
            // we can try scanning the typelib to find the coclass

            typeInfo.GetContainingTypeLib(out ComTypes.ITypeLib typeLib, out int _);
            string typeName = ComRuntimeHelpers.GetNameOfType(typeInfo);

            ComTypeLibDesc   typeLibDesc = ComTypeLibDesc.GetFromTypeLib(typeLib);
            ComTypeClassDesc coclassDesc = typeLibDesc.GetCoClassForInterface(typeName);

            if (coclassDesc == null)
            {
                return(null);
            }

            Guid coclassGuid = coclassDesc.Guid;

            typeLib.GetTypeInfoOfGuid(ref coclassGuid, out ComTypes.ITypeInfo typeInfoCoClass);
            return(typeInfoCoClass);
        }
Example #7
0
        internal ComTypeEnumDesc(ComTypes.ITypeInfo typeInfo, ComTypeLibDesc typeLibDesc) :
            base(typeInfo, typeLibDesc)
        {
            ComTypes.TYPEATTR typeAttr     = ComRuntimeHelpers.GetTypeAttrForTypeInfo(typeInfo);
            string[]          memberNames  = new string[typeAttr.cVars];
            object[]          memberValues = new object[typeAttr.cVars];

            IntPtr p;

            // For each enum member get name and value.
            for (int i = 0; i < typeAttr.cVars; i++)
            {
                typeInfo.GetVarDesc(i, out p);

                // Get the enum member value (as object).
                ComTypes.VARDESC varDesc;

                try
                {
                    varDesc = (ComTypes.VARDESC)Marshal.PtrToStructure(p, typeof(ComTypes.VARDESC));

                    if (varDesc.varkind == ComTypes.VARKIND.VAR_CONST)
                    {
                        memberValues[i] = Marshal.GetObjectForNativeVariant(varDesc.desc.lpvarValue);
                    }
                }
                finally
                {
                    typeInfo.ReleaseVarDesc(p);
                }

                // Get the enum member name
                memberNames[i] = ComRuntimeHelpers.GetNameOfMethod(typeInfo, varDesc.memid);
            }

            _memberNames  = memberNames;
            _memberValues = memberValues;
        }
Example #8
0
        internal static ComTypeLibDesc GetFromTypeLib(ComTypes.ITypeLib typeLib)
        {
            // check whether we have already loaded this type library
            ComTypes.TYPELIBATTR typeLibAttr = ComRuntimeHelpers.GetTypeAttrForTypeLib(typeLib);
            ComTypeLibDesc       typeLibDesc;

            lock (s_cachedTypeLibDesc)
            {
                if (s_cachedTypeLibDesc.TryGetValue(typeLibAttr.guid, out typeLibDesc))
                {
                    return(typeLibDesc);
                }
            }

            typeLibDesc = new ComTypeLibDesc
            {
                Name = ComRuntimeHelpers.GetNameOfLib(typeLib),
                _typeLibAttributes = typeLibAttr
            };

            int countTypes = typeLib.GetTypeInfoCount();

            for (int i = 0; i < countTypes; i++)
            {
                typeLib.GetTypeInfoType(i, out ComTypes.TYPEKIND typeKind);

                typeLib.GetTypeInfo(i, out ComTypes.ITypeInfo typeInfo);
                if (typeKind == ComTypes.TYPEKIND.TKIND_COCLASS)
                {
                    ComTypeClassDesc classDesc = new ComTypeClassDesc(typeInfo, typeLibDesc);
                    typeLibDesc._classes.AddLast(classDesc);
                }
                else if (typeKind == ComTypes.TYPEKIND.TKIND_ENUM)
                {
                    ComTypeEnumDesc enumDesc = new ComTypeEnumDesc(typeInfo, typeLibDesc);
                    typeLibDesc._enums.Add(enumDesc.TypeName, enumDesc);
                }
                else if (typeKind == ComTypes.TYPEKIND.TKIND_ALIAS)
                {
                    ComTypes.TYPEATTR typeAttr = ComRuntimeHelpers.GetTypeAttrForTypeInfo(typeInfo);
                    if (typeAttr.tdescAlias.vt == (short)VarEnum.VT_USERDEFINED)
                    {
                        ComRuntimeHelpers.GetInfoFromType(typeInfo, out string aliasName, out _);

                        typeInfo.GetRefTypeInfo(typeAttr.tdescAlias.lpValue.ToInt32(), out ComTypes.ITypeInfo referencedTypeInfo);

                        ComTypes.TYPEATTR referencedTypeAttr = ComRuntimeHelpers.GetTypeAttrForTypeInfo(referencedTypeInfo);
                        ComTypes.TYPEKIND referencedTypeKind = referencedTypeAttr.typekind;

                        if (referencedTypeKind == ComTypes.TYPEKIND.TKIND_ENUM)
                        {
                            ComTypeEnumDesc enumDesc = new ComTypeEnumDesc(referencedTypeInfo, typeLibDesc);
                            typeLibDesc._enums.Add(aliasName, enumDesc);
                        }
                    }
                }
            }

            // cached the typelib using the guid as the dictionary key
            lock (s_cachedTypeLibDesc)
            {
                s_cachedTypeLibDesc.Add(typeLibAttr.guid, typeLibDesc);
            }

            return(typeLibDesc);
        }
Example #9
0
        private void EnsureScanDefinedMethods()
        {
            if (_comTypeDesc?.Funcs != null)
            {
                return;
            }

            ComTypes.ITypeInfo typeInfo = ComRuntimeHelpers.GetITypeInfoFromIDispatch(DispatchObject);
            if (typeInfo == null)
            {
                _comTypeDesc = ComTypeDesc.CreateEmptyTypeDesc();
                return;
            }

            ComTypes.TYPEATTR typeAttr = ComRuntimeHelpers.GetTypeAttrForTypeInfo(typeInfo);

            if (_comTypeDesc == null)
            {
                lock (s_cacheComTypeDesc)
                {
                    if (s_cacheComTypeDesc.TryGetValue(typeAttr.guid, out _comTypeDesc) &&
                        _comTypeDesc.Funcs != null)
                    {
                        return;
                    }
                }
            }

            ComTypeDesc typeDesc = ComTypeDesc.FromITypeInfo(typeInfo, typeAttr);

            ComMethodDesc getItem = null;
            ComMethodDesc setItem = null;
            Hashtable     funcs   = new Hashtable(typeAttr.cFuncs);
            Hashtable     puts    = new Hashtable();
            Hashtable     putrefs = new Hashtable();

            for (int definedFuncIndex = 0; definedFuncIndex < typeAttr.cFuncs; definedFuncIndex++)
            {
                IntPtr funcDescHandleToRelease = IntPtr.Zero;

                try
                {
                    GetFuncDescForDescIndex(typeInfo, definedFuncIndex, out ComTypes.FUNCDESC funcDesc, out funcDescHandleToRelease);

                    if ((funcDesc.wFuncFlags & (int)ComTypes.FUNCFLAGS.FUNCFLAG_FRESTRICTED) != 0)
                    {
                        // This function is not meant for the script user to use.
                        continue;
                    }

                    ComMethodDesc method = new ComMethodDesc(typeInfo, funcDesc);
                    string        name   = method.Name.ToUpper(CultureInfo.InvariantCulture);

                    if ((funcDesc.invkind & ComTypes.INVOKEKIND.INVOKE_PROPERTYPUT) != 0)
                    {
                        puts.Add(name, method);

                        // for the special dispId == 0, we need to store
                        // the method descriptor for the Do(SetItem) binder.
                        if (method.DispId == ComDispIds.DISPID_VALUE && setItem == null)
                        {
                            setItem = method;
                        }
                        continue;
                    }
                    if ((funcDesc.invkind & ComTypes.INVOKEKIND.INVOKE_PROPERTYPUTREF) != 0)
                    {
                        putrefs.Add(name, method);
                        // for the special dispId == 0, we need to store
                        // the method descriptor for the Do(SetItem) binder.
                        if (method.DispId == ComDispIds.DISPID_VALUE && setItem == null)
                        {
                            setItem = method;
                        }
                        continue;
                    }

                    if (funcDesc.memid == ComDispIds.DISPID_NEWENUM)
                    {
                        funcs.Add("GETENUMERATOR", method);
                        continue;
                    }

                    funcs.Add(name, method);

                    // for the special dispId == 0, we need to store the method descriptor
                    // for the Do(GetItem) binder.
                    if (funcDesc.memid == ComDispIds.DISPID_VALUE)
                    {
                        getItem = method;
                    }
                }
                finally
                {
                    if (funcDescHandleToRelease != IntPtr.Zero)
                    {
                        typeInfo.ReleaseFuncDesc(funcDescHandleToRelease);
                    }
                }
            }

            lock (s_cacheComTypeDesc)
            {
                if (s_cacheComTypeDesc.TryGetValue(typeAttr.guid, out ComTypeDesc cachedTypeDesc))
                {
                    _comTypeDesc = cachedTypeDesc;
                }
                else
                {
                    _comTypeDesc = typeDesc;
                    s_cacheComTypeDesc.Add(typeAttr.guid, _comTypeDesc);
                }
                _comTypeDesc.Funcs   = funcs;
                _comTypeDesc.Puts    = puts;
                _comTypeDesc.PutRefs = putrefs;
                _comTypeDesc.EnsureGetItem(getItem);
                _comTypeDesc.EnsureSetItem(setItem);
            }
        }
Example #10
0
        private void EnsureScanDefinedEvents()
        {
            // _comTypeDesc.Events is null if we have not yet attempted
            // to scan the object for events.
            if (_comTypeDesc?.Events != null)
            {
                return;
            }

            // check type info in the type descriptions cache
            ComTypes.ITypeInfo typeInfo = ComRuntimeHelpers.GetITypeInfoFromIDispatch(DispatchObject);
            if (typeInfo == null)
            {
                _comTypeDesc = ComTypeDesc.CreateEmptyTypeDesc();
                return;
            }

            ComTypes.TYPEATTR typeAttr = ComRuntimeHelpers.GetTypeAttrForTypeInfo(typeInfo);

            if (_comTypeDesc == null)
            {
                lock (s_cacheComTypeDesc)
                {
                    if (s_cacheComTypeDesc.TryGetValue(typeAttr.guid, out _comTypeDesc) &&
                        _comTypeDesc.Events != null)
                    {
                        return;
                    }
                }
            }

            ComTypeDesc typeDesc = ComTypeDesc.FromITypeInfo(typeInfo, typeAttr);

            ComTypes.ITypeInfo classTypeInfo;
            Dictionary <string, ComEventDesc> events;

            var cpc = RuntimeCallableWrapper as ComTypes.IConnectionPointContainer;

            if (cpc == null)
            {
                // No ICPC - this object does not support events
                events = ComTypeDesc.EmptyEvents;
            }
            else if ((classTypeInfo = GetCoClassTypeInfo(RuntimeCallableWrapper, typeInfo)) == null)
            {
                // no class info found - this object may support events
                // but we could not discover those
                events = ComTypeDesc.EmptyEvents;
            }
            else
            {
                events = new Dictionary <string, ComEventDesc>();

                ComTypes.TYPEATTR classTypeAttr = ComRuntimeHelpers.GetTypeAttrForTypeInfo(classTypeInfo);
                for (int i = 0; i < classTypeAttr.cImplTypes; i++)
                {
                    classTypeInfo.GetRefTypeOfImplType(i, out int hRefType);

                    classTypeInfo.GetRefTypeInfo(hRefType, out ComTypes.ITypeInfo interfaceTypeInfo);

                    classTypeInfo.GetImplTypeFlags(i, out ComTypes.IMPLTYPEFLAGS flags);
                    if ((flags & ComTypes.IMPLTYPEFLAGS.IMPLTYPEFLAG_FSOURCE) != 0)
                    {
                        ScanSourceInterface(interfaceTypeInfo, ref events);
                    }
                }

                if (events.Count == 0)
                {
                    events = ComTypeDesc.EmptyEvents;
                }
            }

            lock (s_cacheComTypeDesc)
            {
                if (s_cacheComTypeDesc.TryGetValue(typeAttr.guid, out ComTypeDesc cachedTypeDesc))
                {
                    _comTypeDesc = cachedTypeDesc;
                }
                else
                {
                    _comTypeDesc = typeDesc;
                    s_cacheComTypeDesc.Add(typeAttr.guid, _comTypeDesc);
                }
                _comTypeDesc.Events = events;
            }
        }
Example #11
0
        /// <summary>
        /// Create a stub for the target of the optimized lopop.
        /// </summary>
        /// <returns></returns>
        private Expression MakeIDispatchInvokeTarget()
        {
            Debug.Assert(_varEnumSelector.VariantBuilders.Length == _totalExplicitArgs);

            List <Expression> exprs = new List <Expression>
            {
                //
                // _dispId = ((DispCallable)this).ComMethodDesc.DispId;
                //
                Expression.Assign(
                    DispIdVariable,
                    Expression.Property(_method, typeof(ComMethodDesc).GetProperty(nameof(ComMethodDesc.DispId)))
                    )
            };

            //
            // _dispParams.rgvararg = RuntimeHelpers.UnsafeMethods.ConvertVariantByrefToPtr(ref _paramVariants._element0)
            //
            if (_totalExplicitArgs != 0)
            {
                exprs.Add(
                    Expression.Assign(
                        Expression.Field(
                            DispParamsVariable,
                            typeof(ComTypes.DISPPARAMS).GetField(nameof(ComTypes.DISPPARAMS.rgvarg))
                            ),
                        Expression.Call(
                            typeof(UnsafeMethods).GetMethod(nameof(UnsafeMethods.ConvertVariantByrefToPtr)),
                            VariantArray.GetStructField(ParamVariantsVariable, 0)
                            )
                        )
                    );
            }

            //
            // _dispParams.cArgs = <number_of_params>;
            //
            exprs.Add(
                Expression.Assign(
                    Expression.Field(
                        DispParamsVariable,
                        typeof(ComTypes.DISPPARAMS).GetField(nameof(ComTypes.DISPPARAMS.cArgs))
                        ),
                    Expression.Constant(_totalExplicitArgs)
                    )
                );

            if (_methodDesc.IsPropertyPut)
            {
                //
                // dispParams.cNamedArgs = 1;
                // dispParams.rgdispidNamedArgs = RuntimeHelpers.UnsafeMethods.GetNamedArgsForPropertyPut()
                //
                exprs.Add(
                    Expression.Assign(
                        Expression.Field(
                            DispParamsVariable,
                            typeof(ComTypes.DISPPARAMS).GetField(nameof(ComTypes.DISPPARAMS.cNamedArgs))
                            ),
                        Expression.Constant(1)
                        )
                    );

                exprs.Add(
                    Expression.Assign(
                        PropertyPutDispIdVariable,
                        Expression.Constant(ComDispIds.DISPID_PROPERTYPUT)
                        )
                    );

                exprs.Add(
                    Expression.Assign(
                        Expression.Field(
                            DispParamsVariable,
                            typeof(ComTypes.DISPPARAMS).GetField(nameof(ComTypes.DISPPARAMS.rgdispidNamedArgs))
                            ),
                        Expression.Call(
                            typeof(UnsafeMethods).GetMethod(nameof(UnsafeMethods.ConvertInt32ByrefToPtr)),
                            PropertyPutDispIdVariable
                            )
                        )
                    );
            }
            else
            {
                //
                // _dispParams.cNamedArgs = N;
                //
                exprs.Add(
                    Expression.Assign(
                        Expression.Field(
                            DispParamsVariable,
                            typeof(ComTypes.DISPPARAMS).GetField(nameof(ComTypes.DISPPARAMS.cNamedArgs))
                            ),
                        Expression.Constant(_keywordArgNames.Length)
                        )
                    );
            }

            //
            // _dispatchObject = _dispatch
            // _dispatchPointer = Marshal.GetIDispatchForObject(_dispatchObject);
            //

            exprs.Add(Expression.Assign(DispatchObjectVariable, _dispatch));

            exprs.Add(
                Expression.Assign(
                    DispatchPointerVariable,
                    Expression.Call(
                        ComRuntimeHelpers.GetGetIDispatchForObjectMethod(),
                        DispatchObjectVariable
                        )
                    )
                );

            Expression tryStatements     = GenerateTryBlock();
            Expression finallyStatements = GenerateFinallyBlock();

            exprs.Add(Expression.TryFinally(tryStatements, finallyStatements));

            exprs.Add(ReturnValueVariable);
            var vars = new List <ParameterExpression>();

            foreach (VariantBuilder variant in _varEnumSelector.VariantBuilders)
            {
                if (variant.TempVariable != null)
                {
                    vars.Add(variant.TempVariable);
                }
            }
            return(Expression.Block(vars, exprs));
        }