Example #1
0
        /// <summary>
        /// For a given type, analyze all the functions implemented by it. That means all the argument and return types.
        /// </summary>
        private void ScanDefinedFunctions(ITypeInfo typeInfo, TYPEATTR typeAttributes)
        {
            for (int definedFuncIndex = 0; definedFuncIndex < typeAttributes.cFuncs; definedFuncIndex++)
            {
                IntPtr funcDescHandleToRelease = IntPtr.Zero;

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

                    int offset = 0;

                    // Analyze the argument types
                    for (int paramIndex = 0; paramIndex < funcDesc.cParams; paramIndex++)
                    {
                        var 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);
                    }
                }
            }
        }
Example #2
0
        /// <summary>
        /// Initialize the object with type library attributes
        /// </summary>
        internal bool InitializeWithTypeLibAttrs(TaskLoggingHelper log, bool silent, TYPELIBATTR tlbAttr, ITaskItem originalTaskItem, string targetProcessorArchitecture)
        {
            TYPELIBATTR remappableTlbAttr = tlbAttr;

            ComReference.RemapAdoTypeLib(log, silent, ref remappableTlbAttr);

            // for attribute references, the path is not specified, so we need to get it from the registry
            if (!ComReference.GetPathOfTypeLib(log, silent, ref remappableTlbAttr, out this.fullTypeLibPath))
            {
                return(false);
            }

            // Now that we have the path, we can call InitializeWithPath to get the correct TYPELIBATTR set up
            // and the correct ITypeLib pointer.
            return(InitializeWithPath(log, silent, this.fullTypeLibPath, originalTaskItem, targetProcessorArchitecture));
        }
Example #3
0
        /// <summary>
        /// Analyze the given type looking for dependencies on other type libraries
        /// </summary>
        /// <param name="typeInfo"></param>
        private void AnalyzeTypeInfo(ITypeInfo typeInfo)
        {
            ITypeLib containingTypeLib = null;

            try
            {
                typeInfo.GetContainingTypeLib(out containingTypeLib, out int indexInContainingTypeLib);

                ComReference.GetTypeLibAttrForTypeLib(ref containingTypeLib, out TYPELIBATTR containingTypeLibAttributes);

                // Have we analyzed this type info already? If so skip it.
                var typeInfoId = new AnalyzedTypesInfoKey(
                    containingTypeLibAttributes.guid, containingTypeLibAttributes.wMajorVerNum,
                    containingTypeLibAttributes.wMinorVerNum, containingTypeLibAttributes.lcid, indexInContainingTypeLib);

                // Get enough information about the type to figure out if we want to register it as a dependency

                ComReference.GetTypeAttrForTypeInfo(typeInfo, out TYPEATTR typeAttributes);

                // Is it one of the types we don't care about?
                if (!CanSkipType(typeInfo, containingTypeLib, typeAttributes, containingTypeLibAttributes))
                {
                    _dependencies.Add(containingTypeLibAttributes);

                    if (_analyzedTypes.Add(typeInfoId))
                    {
                        // We haven't already analyzed this type, so rescan
                        ScanImplementedTypes(typeInfo, typeAttributes);
                        ScanDefinedVariables(typeInfo, typeAttributes);
                        ScanDefinedFunctions(typeInfo, typeAttributes);
                    }
                }
                // Make sure if we encounter this type again, we won't rescan it, since we already know we can skip it
                else
                {
                    _analyzedTypes.Add(typeInfoId);
                }
            }
            finally
            {
                if (containingTypeLib != null)
                {
                    _marshalReleaseComObject(containingTypeLib);
                }
            }
        }
Example #4
0
        /// <summary>
        /// For a given type, analyze all the variables defined by it
        /// </summary>
        private void ScanDefinedVariables(ITypeInfo typeInfo, TYPEATTR typeAttributes)
        {
            for (int definedVarIndex = 0; definedVarIndex < typeAttributes.cVars; definedVarIndex++)
            {
                IntPtr varDescHandleToRelease = IntPtr.Zero;

                try
                {
                    ComReference.GetVarDescForVarIndex(typeInfo, definedVarIndex, out VARDESC varDesc, out varDescHandleToRelease);
                    AnalyzeElement(typeInfo, varDesc.elemdescVar);
                }
                finally
                {
                    if (varDescHandleToRelease != IntPtr.Zero)
                    {
                        typeInfo.ReleaseVarDesc(varDescHandleToRelease);
                    }
                }
            }
        }
Example #5
0
        /// <summary>
        /// Initialize the object with a type library path
        /// </summary>
        internal bool InitializeWithPath(TaskLoggingHelper log, bool silent, string path, ITaskItem originalTaskItem, string targetProcessorArchitecture)
        {
            ErrorUtilities.VerifyThrowArgumentNull(path, "path");

            this.taskItem = originalTaskItem;

            // Note that currently we DO NOT remap file ADO references. This is because when pointing to a file on disk,
            // it seems unnatural to remap it to something else - a file reference means "use THIS component".
            // This is still under debate though, and may be revised later.

            // save both the stripped and full path in our object -- for the most part we just need the stripped path, but if
            // we're using tlbimp.exe, we need to pass the full path w/ type lib number to it, or it won't generate the interop
            // assembly correctly.
            this.fullTypeLibPath     = path;
            this.strippedTypeLibPath = ComReference.StripTypeLibNumberFromPath(path, File.Exists);

            // use the unstripped path to actually load the library
            switch (targetProcessorArchitecture)
            {
            case ProcessorArchitecture.AMD64:
            case ProcessorArchitecture.IA64:
                this.typeLibPointer = (ITypeLib)NativeMethods.LoadTypeLibEx(path, (int)NativeMethods.REGKIND.REGKIND_LOAD_TLB_AS_64BIT);
                break;

            case ProcessorArchitecture.X86:
                this.typeLibPointer = (ITypeLib)NativeMethods.LoadTypeLibEx(path, (int)NativeMethods.REGKIND.REGKIND_LOAD_TLB_AS_32BIT);
                break;

            case ProcessorArchitecture.ARM:
            case ProcessorArchitecture.MSIL:
            default:
                // Transmit the flag directly from the .targets files and rely on tlbimp.exe to produce a good error message.
                this.typeLibPointer = (ITypeLib)NativeMethods.LoadTypeLibEx(path, (int)NativeMethods.REGKIND.REGKIND_NONE);
                break;
            }

            try
            {
                // get the type lib attributes from the retrieved interface pointer.
                // do NOT remap file ADO references, since we'd end up with a totally different reference than specified.
                ComReference.GetTypeLibAttrForTypeLib(ref this.typeLibPointer, out this.attr);

                // get the type lib name from the retrieved interface pointer
                if (!ComReference.GetTypeLibNameForITypeLib(
                        log,
                        silent,
                        this.typeLibPointer,
                        GetTypeLibId(log),
                        out this.typeLibName))
                {
                    ReleaseTypeLibPtr();
                    return(false);
                }
            }
            catch (COMException)
            {
                ReleaseTypeLibPtr();
                throw;
            }

            return(true);
        }