通过代码在typelib文件中查找依赖类型库

时间:2017-07-12 16:22:52

标签: com

寻找一种方法来查找类型库的依赖类型库。例如,在IDL中声明依赖库时,常见的依赖项是stdole2.tlb并声明为:

导入库(" STDOLE2.TLB&#34);

我可以使用OleView.exe来查看这些依赖项,但我试图找出如何在代码中执行此操作。在ITypeLib或ITypeLib2接口中似乎没有可以获取这些依赖关系的任何成员。我已经搜索了OLE自动化参考,但还没有找到一种方法来获取接口。

它们是否以某种方式处于类型库的二进制资源格式?

任何可以指出我正确方向的人?

1 个答案:

答案 0 :(得分:3)

以下是类型库的GetDependencies函数的完整实现。

这将返回unordered_setITypeLibPtr智能指针。请注意散列函数,它允许在unordered_set和其他散列容器中使用这些智能指针。

这只返回第一级依赖项。如果这些类型库具有其他依赖项,则可以以某种递归方式使用此方法来获取一组完整的依赖项(第一级和更高级别)。

循环引用(例如IInterfaceA具有返回IInterfaceB指针的属性,而IInterfaceB具有返回IInterfaceA指针的属性)通过存储{在浏览类型库时访问ITypeInfo的{​​3}}。

此代码旨在抛出unordered_set个异常(除了使用_com_error时可能发生的任何STL异常)。适当处理这些。如果您不想处理unordered_set例外情况,请使用您自己的_com_util::CheckError值的错误处理逻辑替换HRESULT次调用。

#include <windows.h>
#include <comdef.h>
#include <unordered_set>

// gets dependencies of a type library
std::unordered_set<ITypeLibPtr> GetDependencies(ITypeLib* pTypeLib);

// gathers dependencies of a type library
void GetDependenciesHelper(ITypeLib* pTypeLib, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput);

// gathers dependencies of a type
void GetDependenciesHelper(ITypeLib* pTypeLib, ITypeInfo* pTypeInfo, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput);

// gathers dependencies of a reference
void GetDependenciesHelper(ITypeLib* pTypeLib, ITypeInfo* pTypeInfo, HREFTYPE hRefType, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput);

// gathers dependencies of a reference
void GetDependenciesHelper(ITypeLib* pTypeLib, ITypeInfo* pTypeInfo, TYPEDESC& referencedTypeDescription, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput);

// gathers dependencies of a function declaration
void GetDependenciesHelper(ITypeLib* pTypeLib, ITypeInfo* pTypeInfo, FUNCDESC& functionDescription, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput);

// gathers dependencies of a variable declaration
void GetDependenciesHelper(ITypeLib* pTypeLib, ITypeInfo* pTypeInfo, VARDESC& variableDescription, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput);

// gathers dependencies of an array declaration
void GetDependenciesHelper(ITypeLib* pTypeLib, ITypeInfo* pTypeInfo, ARRAYDESC& arrayDescription, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput);

// gathers dependencies of an array element declaration
void GetDependenciesHelper(ITypeLib* pTypeLib, ITypeInfo* pTypeInfo, ELEMDESC& elementDescription, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput);

namespace std
{
    // provides a function for hashing ITypeLibPtr instances by their raw address
    template<> struct hash<ITypeLibPtr>
    {
        size_t operator()(ITypeLibPtr const& pTypeLib) const { return pTypeLib; }
    };
    // provides a function for hashing ITypeInfo instances by their raw address
    template<> struct hash<ITypeInfoPtr>
    {
        size_t operator()(ITypeInfoPtr const& pTypeInfo) const { return pTypeInfo; }
    };
}

std::unordered_set<ITypeLibPtr> GetDependencies(ITypeLib* pTypeLib)
{
    // get dependencies
    std::unordered_set<ITypeLibPtr> output;
    std::unordered_set<ITypeInfoPtr> history;
    GetDependenciesHelper(pTypeLib, &history, &output);
    return output;
}

void GetDependenciesHelper(ITypeLib* pTypeLib, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput)
{
    // iterate over type infos
    auto typeInfoCount = pTypeLib->GetTypeInfoCount();
    for (UINT typeInfoIndex = 0; typeInfoIndex < typeInfoCount; ++typeInfoIndex)
    {
        // get type info
        ITypeInfoPtr pTypeInfo;
        _com_util::CheckError(pTypeLib->GetTypeInfo(typeInfoIndex, &pTypeInfo));

        // get dependencies for type info
        GetDependenciesHelper(pTypeLib, pTypeInfo, pHistory, pOutput);
    }
}

void GetDependenciesHelper(ITypeLib* pTypeLib, ITypeInfo* pTypeInfo, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput)
{
    // short-circuit if we've already processed this type info
    if (!pHistory->insert(pTypeInfo).second)
        return;

    // get type attributes
    TYPEATTR* typeAttributes;
    _com_util::CheckError(pTypeInfo->GetTypeAttr(&typeAttributes));
    try
    {
        // special handling for aliases
        if (typeAttributes->typekind == TKIND_ALIAS)
        {
            // get dependencies of the alias
            GetDependenciesHelper(pTypeLib, pTypeInfo, typeAttributes->tdescAlias, pHistory, pOutput);
        }
        else
        {
            // iterate over implemented types
            auto implementedTypeCount = typeAttributes->cImplTypes;
            for (WORD implementedTypeIndex = 0; implementedTypeIndex < implementedTypeCount; ++implementedTypeIndex)
            {
                // get type reference
                HREFTYPE hRefType;
                _com_util::CheckError(pTypeInfo->GetRefTypeOfImplType(implementedTypeIndex, &hRefType));

                // get dependencies of the implementation
                GetDependenciesHelper(pTypeLib, pTypeInfo, hRefType, pHistory, pOutput);
            }

            // iterate over functions
            auto functionCount = typeAttributes->cFuncs;
            for (WORD functionIndex = 0; functionIndex < functionCount; ++functionIndex)
            {
                // get function description
                FUNCDESC* functionDescription;
                _com_util::CheckError(pTypeInfo->GetFuncDesc(functionIndex, &functionDescription));
                try
                {
                    // get dependencies of the function declaration
                    GetDependenciesHelper(pTypeLib, pTypeInfo, *functionDescription, pHistory, pOutput);
                }
                catch (...)
                {
                    // release function description
                    pTypeInfo->ReleaseFuncDesc(functionDescription);
                    throw;
                }

                // release function description
                pTypeInfo->ReleaseFuncDesc(functionDescription);
            }

            // iterate over variables
            auto variableCount = typeAttributes->cVars;
            for (WORD variableIndex = 0; variableIndex < variableCount; ++variableIndex)
            {
                // get variable description
                VARDESC* variableDescription;
                _com_util::CheckError(pTypeInfo->GetVarDesc(variableIndex, &variableDescription));
                try
                {
                    // get dependencies of the variable declaration
                    GetDependenciesHelper(pTypeLib, pTypeInfo, *variableDescription, pHistory, pOutput);
                }
                catch (...)
                {
                    // release variable description
                    pTypeInfo->ReleaseVarDesc(variableDescription);
                    throw;
                }

                // release variable description
                pTypeInfo->ReleaseVarDesc(variableDescription);
            }
        }
    }
    catch (...)
    {
        // release type attributes
        pTypeInfo->ReleaseTypeAttr(typeAttributes);
        throw;
    }

    // release type attributes
    pTypeInfo->ReleaseTypeAttr(typeAttributes);
}

void GetDependenciesHelper(ITypeLib* pTypeLib, ITypeInfo* pTypeInfo, HREFTYPE hRefType, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput)
{
    // get referenced type info
    ITypeInfoPtr referencedTypeInfo;
    _com_util::CheckError(pTypeInfo->GetRefTypeInfo(hRefType, &referencedTypeInfo));

    // get referenced type lib
    ITypeLibPtr referencedTypeLibrary;
    UINT referencedTypeInfoIndex;
    _com_util::CheckError(referencedTypeInfo->GetContainingTypeLib(&referencedTypeLibrary, &referencedTypeInfoIndex));

    // store dependency
    if (referencedTypeLibrary != pTypeLib)
        pOutput->insert(referencedTypeLibrary);
}

void GetDependenciesHelper(ITypeLib* pTypeLib, ITypeInfo* pTypeInfo, TYPEDESC& referencedTypeDescription, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput)
{
    switch (referencedTypeDescription.vt)
    {
        case VT_PTR:
        {
            // get dependencies of the pointer declaration
            GetDependenciesHelper(pTypeLib, pTypeInfo, *referencedTypeDescription.lptdesc, pHistory, pOutput);
            break;
        }
        case VT_CARRAY:
        {
            // get dependencies of the array declaration
            GetDependenciesHelper(pTypeLib, pTypeInfo, *referencedTypeDescription.lpadesc, pHistory, pOutput);
            break;
        }
        case VT_USERDEFINED:
        {
            // get dependencies of the UDT reference
            GetDependenciesHelper(pTypeLib, pTypeInfo, referencedTypeDescription.hreftype, pHistory, pOutput);
            break;
        }
    }
}

void GetDependenciesHelper(ITypeLib* pTypeLib, ITypeInfo* pTypeInfo, FUNCDESC& functionDescription, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput)
{
    // get dependencies of the function return value
    GetDependenciesHelper(pTypeLib, pTypeInfo, functionDescription.elemdescFunc, pHistory, pOutput);

    // iterate over parameters
    auto parameterCount = functionDescription.cParams;
    for (SHORT parameterIndex = 0; parameterIndex < parameterCount; ++parameterIndex)
    {
        // get parameter description
        auto& parameterDescription = functionDescription.lprgelemdescParam[parameterIndex];

        // get dependencies of the parameter declaration
        GetDependenciesHelper(pTypeLib, pTypeInfo, parameterDescription, pHistory, pOutput);
    }
}

void GetDependenciesHelper(ITypeLib* pTypeLib, ITypeInfo* pTypeInfo, VARDESC& variableDescription, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput)
{
    // get dependencies of the variable declaration
    GetDependenciesHelper(pTypeLib, pTypeInfo, variableDescription.elemdescVar, pHistory, pOutput);
}

void GetDependenciesHelper(ITypeLib* pTypeLib, ITypeInfo* pTypeInfo, ARRAYDESC& arrayDescription, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput)
{
    // get dependencies of the array declaration
    GetDependenciesHelper(pTypeLib, pTypeInfo, arrayDescription.tdescElem, pHistory, pOutput);
}

void GetDependenciesHelper(ITypeLib* pTypeLib, ITypeInfo* pTypeInfo, ELEMDESC& elementDescription, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput)
{
    // get dependencies of the array element declaration
    GetDependenciesHelper(pTypeLib, pTypeInfo, elementDescription.tdesc, pHistory, pOutput);
}